os/persistentdata/persistentstorage/dbms/tdbms/t_dbthrd.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     2
// All rights reserved.
sl@0
     3
// This component and the accompanying materials are made available
sl@0
     4
// under the terms of "Eclipse Public License v1.0"
sl@0
     5
// which accompanies this distribution, and is available
sl@0
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     7
//
sl@0
     8
// Initial Contributors:
sl@0
     9
// Nokia Corporation - initial contribution.
sl@0
    10
//
sl@0
    11
// Contributors:
sl@0
    12
//
sl@0
    13
// Description:
sl@0
    14
//
sl@0
    15
sl@0
    16
#include "t_dbstress.h"
sl@0
    17
sl@0
    18
const TInt KCashLimit=500;
sl@0
    19
const TInt KOverdraftLimit=100;
sl@0
    20
sl@0
    21
const TInt KMinHeap=0x2000;
sl@0
    22
const TInt KMaxHeap=0x20000;
sl@0
    23
#ifdef _DEBUG
sl@0
    24
const TInt KAllocFailRate=1000;
sl@0
    25
#endif
sl@0
    26
sl@0
    27
LOCAL_D TBuf<256> Sql;
sl@0
    28
LOCAL_D	TBuf8<256> LogBuf;
sl@0
    29
sl@0
    30
class CThread : public CBase
sl@0
    31
	{
sl@0
    32
public:
sl@0
    33
	static TInt Entry(TAny*);
sl@0
    34
protected:
sl@0
    35
	CThread() {}
sl@0
    36
	~CThread();
sl@0
    37
private:
sl@0
    38
	static void EntryL();
sl@0
    39
	void GoL();
sl@0
    40
	void ConstructL();
sl@0
    41
	void OpenViewsL();
sl@0
    42
	void RecoverL();
sl@0
    43
	void CompactL();
sl@0
    44
	void Rollback();
sl@0
    45
	void Reset();
sl@0
    46
	void WorkL();
sl@0
    47
	void TransactionL();
sl@0
    48
	void AccountL(TInt anAccount);
sl@0
    49
	void StatementTimeL();
sl@0
    50
	void VerifyL();
sl@0
    51
//
sl@0
    52
	void LogSize();
sl@0
    53
private:
sl@0
    54
	RFs iFs;
sl@0
    55
	RFile iLog;
sl@0
    56
	CFileStore* iStore;
sl@0
    57
	RDbStoreDatabase iData;
sl@0
    58
	TBool iOpen;
sl@0
    59
	RDbView iAccs;
sl@0
    60
	RDbView iTrans;
sl@0
    61
	TInt iError;
sl@0
    62
	TInt iPoint;
sl@0
    63
	};
sl@0
    64
sl@0
    65
GLDEF_C TInt StartThread(RThread& aThread,TRequestStatus& aStat)
sl@0
    66
	{
sl@0
    67
	TInt r=aThread.Create(_L("Thread"),CThread::Entry,KDefaultStackSize,KMinHeap,KMaxHeap,NULL);
sl@0
    68
	if (r==KErrNone)
sl@0
    69
		{
sl@0
    70
		aThread.SetPriority(EPriorityLess);
sl@0
    71
		aThread.Logon(aStat);
sl@0
    72
		aThread.Resume();
sl@0
    73
		RunTimer.Start();
sl@0
    74
		}
sl@0
    75
	return r;
sl@0
    76
	}
sl@0
    77
sl@0
    78
TInt CThread::Entry(TAny*)
sl@0
    79
	{
sl@0
    80
	CTrapCleanup* cleanup=CTrapCleanup::New();
sl@0
    81
	if (cleanup==NULL)
sl@0
    82
		return KErrNoMemory;
sl@0
    83
	TRAPD(r,EntryL());
sl@0
    84
	delete cleanup;
sl@0
    85
	return r;
sl@0
    86
	}
sl@0
    87
sl@0
    88
void CThread::EntryL()
sl@0
    89
	{
sl@0
    90
	CThread* self=new(ELeave) CThread;
sl@0
    91
	CleanupStack::PushL(self);
sl@0
    92
	self->ConstructL();
sl@0
    93
	self->GoL();		// never returns
sl@0
    94
	}
sl@0
    95
sl@0
    96
CThread::~CThread()
sl@0
    97
	{//The destructor is never ever executed! See CThread::EntryL() for details!
sl@0
    98
	iAccs.Close();
sl@0
    99
	iTrans.Close();
sl@0
   100
	iData.Close();
sl@0
   101
	delete iStore;
sl@0
   102
	iLog.Close();
sl@0
   103
	TInt err = iFs.Delete(KLogFile);
sl@0
   104
	if(err != KErrNone)
sl@0
   105
		{
sl@0
   106
		RDebug::Print(_L("Error %d deleting \"%S\" file.\n"), err, &KLogFile);
sl@0
   107
		}
sl@0
   108
	iFs.Close();
sl@0
   109
	}
sl@0
   110
sl@0
   111
void CThread::ConstructL()
sl@0
   112
	{
sl@0
   113
	User::LeaveIfError(iFs.Connect());
sl@0
   114
	User::LeaveIfError(iFs.SetSessionPath(KTestDir));
sl@0
   115
	User::LeaveIfError(iLog.Replace(iFs,KLogFile,EFileWrite|EFileStreamText));
sl@0
   116
	iStore=CFileStore::OpenL(iFs,KTestDatabase,EFileRead|EFileWrite|EFileWriteDirectIO);
sl@0
   117
	LogSize();
sl@0
   118
	iData.OpenL(iStore,iStore->Root());
sl@0
   119
	}
sl@0
   120
sl@0
   121
//
sl@0
   122
// Never exits
sl@0
   123
//
sl@0
   124
void CThread::GoL()
sl@0
   125
	{
sl@0
   126
	__UHEAP_SETFAIL(RHeap::ETrueRandom,KAllocFailRate);
sl@0
   127
	for (;;)
sl@0
   128
		{
sl@0
   129
		TRAPD(r,WorkL());
sl@0
   130
		NewCount=OldCount;
sl@0
   131
		LogBuf.Format(_L8(" *** Point %d with code %d"),iPoint,r);
sl@0
   132
		iLog.Write(LogBuf);
sl@0
   133
		LogSize();
sl@0
   134
		iError=r;
sl@0
   135
		Rollback();
sl@0
   136
		LogSize();
sl@0
   137
		if (r==KErrDiskFull)
sl@0
   138
			User::Leave(r);
sl@0
   139
		}
sl@0
   140
	}
sl@0
   141
sl@0
   142
//
sl@0
   143
// Report the file size
sl@0
   144
//
sl@0
   145
void CThread::LogSize()
sl@0
   146
	{
sl@0
   147
	TInt size;
sl@0
   148
	if (iStore->File().Size(size)==KErrNone)
sl@0
   149
		{
sl@0
   150
		LogBuf.Format(_L8("\nFile size=%d"),size);
sl@0
   151
		iLog.Write(LogBuf);
sl@0
   152
		}
sl@0
   153
	}
sl@0
   154
sl@0
   155
void CThread::Rollback()
sl@0
   156
	{
sl@0
   157
	if (iOpen)
sl@0
   158
		{
sl@0
   159
		iLog.Write(_L8("\nCancel"));
sl@0
   160
		iAccs.Cancel();
sl@0
   161
		iTrans.Cancel();
sl@0
   162
		}
sl@0
   163
	if (iData.InTransaction())
sl@0
   164
		{
sl@0
   165
		iLog.Write(_L8("\nRollback"));
sl@0
   166
		iData.Rollback();
sl@0
   167
		}
sl@0
   168
	}
sl@0
   169
sl@0
   170
void CThread::Reset()
sl@0
   171
	{
sl@0
   172
	iLog.Write(_L8("\nReset"));
sl@0
   173
	TEST(iOpen);
sl@0
   174
	iAccs.Reset();
sl@0
   175
	iTrans.Reset();
sl@0
   176
	}
sl@0
   177
sl@0
   178
void CThread::RecoverL()
sl@0
   179
	{
sl@0
   180
	iPoint=70;
sl@0
   181
	User::LeaveIfError(iLog.Write(_L8("\nRecovering")));
sl@0
   182
	if (iOpen)
sl@0
   183
		{
sl@0
   184
		iAccs.Close();
sl@0
   185
		iTrans.Close();
sl@0
   186
		iOpen=EFalse;
sl@0
   187
		}
sl@0
   188
	User::LeaveIfError(iData.Recover());
sl@0
   189
	}
sl@0
   190
sl@0
   191
void CThread::CompactL()
sl@0
   192
	{
sl@0
   193
	iPoint=90;
sl@0
   194
	User::LeaveIfError(iLog.Write(_L8("\nCompacting")));
sl@0
   195
	TInt b=iStore->ReclaimL();
sl@0
   196
	b-=iStore->CompactL();
sl@0
   197
	iStore->CommitL();
sl@0
   198
	LogBuf.Format(_L8(": %d bytes reclaimed"),b);
sl@0
   199
	User::LeaveIfError(iLog.Write(LogBuf));
sl@0
   200
	}
sl@0
   201
sl@0
   202
void CThread::OpenViewsL()
sl@0
   203
	{
sl@0
   204
	iPoint=80;
sl@0
   205
	User::LeaveIfError(iLog.Write(_L8("\nOpening")));
sl@0
   206
	User::LeaveIfError(iAccs.Prepare(iData,_L("select id,balance,statement_balance from accounts")));
sl@0
   207
	TInt r=iTrans.Prepare(iData,_L("select t_date,from_id,to_id,amount from transactions"));
sl@0
   208
	if (r!=KErrNone)
sl@0
   209
		{
sl@0
   210
		iAccs.Close();
sl@0
   211
		User::Leave(r);
sl@0
   212
		}
sl@0
   213
	iOpen=ETrue;
sl@0
   214
	}
sl@0
   215
sl@0
   216
void CThread::WorkL()
sl@0
   217
	{
sl@0
   218
	iPoint=0;
sl@0
   219
	switch (iError)
sl@0
   220
		{
sl@0
   221
	case KErrDied:
sl@0
   222
		Rollback();
sl@0
   223
		break;
sl@0
   224
	case KErrNotReady:
sl@0
   225
		Reset();
sl@0
   226
		break;
sl@0
   227
	case KErrCorrupt:
sl@0
   228
		RecoverL();
sl@0
   229
		break;
sl@0
   230
		}
sl@0
   231
	iPoint=1;
sl@0
   232
	for (;;)
sl@0
   233
		{
sl@0
   234
		LogSize();
sl@0
   235
		if (!iOpen)
sl@0
   236
			OpenViewsL();
sl@0
   237
		switch (Random(100))
sl@0
   238
			{
sl@0
   239
		case 0:	case 1:
sl@0
   240
			StatementTimeL();
sl@0
   241
			break;
sl@0
   242
		case 2: case 3:
sl@0
   243
			RecoverL();
sl@0
   244
			break;
sl@0
   245
		case 4: // case 5: case 6: case 7: case 8: case 9:
sl@0
   246
			CompactL();
sl@0
   247
			break;
sl@0
   248
		default:
sl@0
   249
			TransactionL();
sl@0
   250
			break;
sl@0
   251
			}
sl@0
   252
		}
sl@0
   253
	}
sl@0
   254
sl@0
   255
void CThread::AccountL(TInt anAccount)
sl@0
   256
	{
sl@0
   257
	Sql.Format(_L("id=%d"),anAccount);
sl@0
   258
	iAccs.FirstL();
sl@0
   259
	TEST(iAccs.FindL(iAccs.EForwards,Sql)>=0);
sl@0
   260
	}
sl@0
   261
sl@0
   262
//
sl@0
   263
// generate and add a single transaction
sl@0
   264
//
sl@0
   265
void CThread::TransactionL()
sl@0
   266
	{
sl@0
   267
	iPoint=2;
sl@0
   268
	User::LeaveIfError(iLog.Write(_L8("\nTransaction")));
sl@0
   269
	TInt from;
sl@0
   270
	if (Random(3)==0)
sl@0
   271
		from=ECash;
sl@0
   272
	else
sl@0
   273
		from=Random(KAccountIDs);
sl@0
   274
	TInt to=(Random(KAccountIDs-1)+from+1)%KAccountIDs;
sl@0
   275
	AccountL(from);
sl@0
   276
	iAccs.GetL();
sl@0
   277
	TEST(iAccs.ColInt(1)==from);
sl@0
   278
	TInt avail=iAccs.ColInt(2)+KOverdraftLimit;
sl@0
   279
	TInt amount;
sl@0
   280
	if (to==ECash)
sl@0
   281
		{
sl@0
   282
		if (avail<10)
sl@0
   283
			return;
sl@0
   284
		amount=10*(1+Random(Min(avail,KCashLimit)/10));
sl@0
   285
		}
sl@0
   286
	else
sl@0
   287
		{
sl@0
   288
		amount=1+Random(100);
sl@0
   289
		if (Random(100)<5)
sl@0
   290
			amount*=10;
sl@0
   291
		if (Random(100)<5)
sl@0
   292
			amount*=10;
sl@0
   293
		while (amount>avail)
sl@0
   294
			amount/=4;
sl@0
   295
		if (amount==0)
sl@0
   296
			return;
sl@0
   297
		}
sl@0
   298
	iPoint=3;
sl@0
   299
	LogBuf.Format(_L8(" %08d: %d -> %d, %5d"),++TransId,from,to,amount);
sl@0
   300
	User::LeaveIfError(iLog.Write(LogBuf));
sl@0
   301
	iPoint=4;
sl@0
   302
	iData.Begin();
sl@0
   303
	iTrans.InsertL();
sl@0
   304
	iTrans.SetColL(1,TransId);
sl@0
   305
	iTrans.SetColL(2,from);
sl@0
   306
	iTrans.SetColL(3,to);
sl@0
   307
	iTrans.SetColL(4,amount);
sl@0
   308
	iPoint=5;
sl@0
   309
	iTrans.PutL();
sl@0
   310
	iPoint=6;
sl@0
   311
	iAccs.UpdateL();	// from
sl@0
   312
	TInt frombalance=iAccs.ColInt(2)-amount;
sl@0
   313
	iAccs.SetColL(2,frombalance);
sl@0
   314
	iPoint=7;
sl@0
   315
	iAccs.PutL();
sl@0
   316
	iPoint=8;
sl@0
   317
	AccountL(to);
sl@0
   318
	iPoint=9;
sl@0
   319
	iAccs.UpdateL();	// to
sl@0
   320
	TInt tobalance=iAccs.ColInt(2)+amount;
sl@0
   321
	iAccs.SetColL(2,tobalance);
sl@0
   322
	iPoint=10;
sl@0
   323
	iAccs.PutL();
sl@0
   324
	iPoint=11;
sl@0
   325
// this will invoke commit, so update counts now
sl@0
   326
	NewCount=OldCount+1;
sl@0
   327
	TInt r=iData.Commit();
sl@0
   328
	if (r!=KErrNone)
sl@0
   329
		{
sl@0
   330
		NewCount=OldCount;
sl@0
   331
		User::Leave(r);
sl@0
   332
		}
sl@0
   333
// succeeded
sl@0
   334
	OldCount=NewCount;
sl@0
   335
	LogBuf.Format(_L8("; [%d,%d]"),frombalance,tobalance);
sl@0
   336
	iLog.Write(LogBuf);
sl@0
   337
	}
sl@0
   338
sl@0
   339
//
sl@0
   340
// deliver statements
sl@0
   341
//
sl@0
   342
void CThread::StatementTimeL()
sl@0
   343
	{
sl@0
   344
	iPoint=50;
sl@0
   345
	User::LeaveIfError(iLog.Write(_L8("\nStatement")));
sl@0
   346
	iPoint=51;
sl@0
   347
	VerifyL();
sl@0
   348
	// discard transactions
sl@0
   349
	iPoint=52;
sl@0
   350
	iData.Begin();
sl@0
   351
	for (iTrans.BeginningL();iTrans.NextL();)
sl@0
   352
		iTrans.DeleteL();
sl@0
   353
	for (iAccs.BeginningL();iAccs.NextL();)
sl@0
   354
		{
sl@0
   355
		iAccs.UpdateL();
sl@0
   356
		iAccs.SetColL(3,iAccs.ColInt(2));	// set statement balance
sl@0
   357
		iAccs.PutL();
sl@0
   358
		}
sl@0
   359
	iPoint=53;
sl@0
   360
	NewCount=0;
sl@0
   361
	TInt r=iData.Commit();
sl@0
   362
	if (r!=KErrNone)
sl@0
   363
		{
sl@0
   364
		NewCount=OldCount;
sl@0
   365
		User::Leave(r);
sl@0
   366
		}
sl@0
   367
	OldCount=NewCount;
sl@0
   368
	}
sl@0
   369
sl@0
   370
void CThread::VerifyL()
sl@0
   371
	{
sl@0
   372
	TInt balance[KAccountIDs];
sl@0
   373
	TEST(iAccs.CountL()==KAccountIDs);
sl@0
   374
	for (iAccs.BeginningL();iAccs.NextL();)
sl@0
   375
		{
sl@0
   376
		iAccs.GetL();
sl@0
   377
		TInt id=iAccs.ColInt(1);
sl@0
   378
		balance[id]=iAccs.ColInt(3);
sl@0
   379
		}
sl@0
   380
	TInt transact=0;
sl@0
   381
	for (iTrans.BeginningL();iTrans.NextL();)
sl@0
   382
		{
sl@0
   383
		++transact;
sl@0
   384
		iTrans.GetL();
sl@0
   385
		TInt from=iTrans.ColInt(2);
sl@0
   386
		TInt to=iTrans.ColInt(3);
sl@0
   387
		TInt amount=iTrans.ColInt(4);
sl@0
   388
		balance[from]-=amount;
sl@0
   389
		balance[to]+=amount;
sl@0
   390
		}
sl@0
   391
	TEST(transact==iTrans.CountL());
sl@0
   392
	for (iAccs.BeginningL();iAccs.NextL();)
sl@0
   393
		{
sl@0
   394
		iAccs.GetL();
sl@0
   395
		TInt id=iAccs.ColInt(1);
sl@0
   396
		if (balance[id]!=iAccs.ColInt(2))
sl@0
   397
			User::Panic(_L("Oh-oh"),4321);
sl@0
   398
		}
sl@0
   399
	}