os/security/authorisation/userpromptservice/database/source/upsdbw.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
* Implements a writable interface for UPS Database.
sl@0
    16
*
sl@0
    17
*/
sl@0
    18
sl@0
    19
sl@0
    20
/**
sl@0
    21
 @file
sl@0
    22
 @internalTechnology
sl@0
    23
 @released
sl@0
    24
*/
sl@0
    25
sl@0
    26
#include "upsdbw.h"
sl@0
    27
#include "upscommon.h"
sl@0
    28
sl@0
    29
using namespace UserPromptService;
sl@0
    30
sl@0
    31
CDecisionDbW::CDecisionDbW()
sl@0
    32
/**
sl@0
    33
	Constructor for writable decision database object
sl@0
    34
 */
sl@0
    35
	{
sl@0
    36
	
sl@0
    37
	}
sl@0
    38
sl@0
    39
	
sl@0
    40
CDecisionDbW::~CDecisionDbW()
sl@0
    41
/**
sl@0
    42
	Destructor for writable decision database object
sl@0
    43
 */
sl@0
    44
	{
sl@0
    45
	iDatabase.Close();
sl@0
    46
	delete iDbName;
sl@0
    47
	delete iStore;
sl@0
    48
	}
sl@0
    49
sl@0
    50
sl@0
    51
EXPORT_C CDecisionDbW* CDecisionDbW::NewL(const TDesC& aDbName, RFs& aFs)
sl@0
    52
/**
sl@0
    53
	Creates a writable decision database object and connects to the database.
sl@0
    54
	If the database does not exist or is corrupted, a new decision database is created.
sl@0
    55
	The function leaves, if creation of the object or connection to the database fail.
sl@0
    56
		
sl@0
    57
	@param	 aDbName The path of the decision database
sl@0
    58
	@param   aFs     Handle to the file server session
sl@0
    59
	
sl@0
    60
	@return  A pointer to the newly allocated database object, if creation and connection are successful. 
sl@0
    61
 */
sl@0
    62
	{
sl@0
    63
	CDecisionDbW* self = CDecisionDbW::NewLC(aDbName, aFs);
sl@0
    64
	CleanupStack::Pop(self);
sl@0
    65
	return self;
sl@0
    66
	}
sl@0
    67
sl@0
    68
	
sl@0
    69
EXPORT_C CDecisionDbW* CDecisionDbW::NewLC(const TDesC& aDbName, RFs& aFs)
sl@0
    70
/**
sl@0
    71
	Creates a writable decision database object and connects to the database.
sl@0
    72
	If the database does not exist or is corrupted, a new decision database is created.
sl@0
    73
	The function leaves, if creation of the object or connection to the database fail.
sl@0
    74
		
sl@0
    75
	@param	aDbName The path of the decision database
sl@0
    76
	param   aFs		Handle to the file server session
sl@0
    77
	
sl@0
    78
	@return A pointer to the newly allocated database object, if creation and connection 
sl@0
    79
			are successful. The pointer is also put onto the cleanup stack.
sl@0
    80
 */
sl@0
    81
	{
sl@0
    82
	CDecisionDbW* self = new (ELeave) CDecisionDbW();
sl@0
    83
	CleanupStack::PushL(self);
sl@0
    84
	self->ConstructL(aDbName, aFs);
sl@0
    85
	return self;
sl@0
    86
	}
sl@0
    87
sl@0
    88
	
sl@0
    89
void CDecisionDbW::ConstructL(const TDesC& aDbName, RFs& aFs)
sl@0
    90
/**
sl@0
    91
	Second phase constructor for the decision database object. Connects to the decision database.
sl@0
    92
	If the database does not existed or is corrupted, creates a new one. The function leaves,
sl@0
    93
	if both database connection and creation fail.
sl@0
    94
	
sl@0
    95
	@param aDbName The path of the decision database
sl@0
    96
	@param aFs		Handle to the file server session
sl@0
    97
 */
sl@0
    98
	{
sl@0
    99
	//Construct the name of UPS decision database
sl@0
   100
	iDbName = aDbName.AllocL();
sl@0
   101
	
sl@0
   102
	//First try to open the decision database
sl@0
   103
	TRAPD(error,OpenDatabaseL(aFs));
sl@0
   104
	
sl@0
   105
	if((error == KErrNoMemory) || (error == KErrDiskFull))
sl@0
   106
		{
sl@0
   107
		User::Leave(error);
sl@0
   108
		}
sl@0
   109
	
sl@0
   110
	// Makes sure that DB file is writable. (DEF122590)
sl@0
   111
	aFs.SetAtt(iDbName->Des(),0, KEntryAttReadOnly);
sl@0
   112
		
sl@0
   113
	if(error != KErrNone)
sl@0
   114
		{
sl@0
   115
		DEBUG_PRINTF2(_L("%S database file does not exist or is corrupted."), iDbName);
sl@0
   116
		//The decision database does not exist or is corrupted, create a new one
sl@0
   117
		CreateDatabaseL(aFs);
sl@0
   118
		
sl@0
   119
		//Create a decision table in the decision database
sl@0
   120
		CreateTableL();
sl@0
   121
		
sl@0
   122
		//Create an index on the decision table
sl@0
   123
		CreateIndexL();
sl@0
   124
		}
sl@0
   125
	}
sl@0
   126
sl@0
   127
	
sl@0
   128
void CDecisionDbW::OpenDatabaseL(RFs& aFs)
sl@0
   129
/**
sl@0
   130
	Opens the decision database.
sl@0
   131
	@param aFs	Handle to the file server session
sl@0
   132
 */
sl@0
   133
	{
sl@0
   134
	DEBUG_PRINTF2(_L("%S database file is being opened."), iDbName);
sl@0
   135
	
sl@0
   136
	iStore = CPermanentFileStore::OpenL(aFs, *iDbName, EFileRead|EFileWrite);
sl@0
   137
	iDatabase.OpenL(iStore, iStore->Root());
sl@0
   138
	
sl@0
   139
	//Database does exist. However, make sure that the decision table also exists
sl@0
   140
	CDbTableNames *tables = iDatabase.TableNamesL();
sl@0
   141
	CleanupStack::PushL(tables);
sl@0
   142
	if(1 != tables->Count())
sl@0
   143
		{
sl@0
   144
		DEBUG_PRINTF(_L("The decision table could not be found in the database file!"));
sl@0
   145
		User::Leave(KErrNotFound);
sl@0
   146
		}
sl@0
   147
	CleanupStack::PopAndDestroy(tables);
sl@0
   148
	
sl@0
   149
	//OK. The decision table does exist. What about the decision index?
sl@0
   150
	CDbIndexNames *indexes = iDatabase.IndexNamesL(KDecisionTable);
sl@0
   151
	CleanupStack::PushL(indexes);
sl@0
   152
	if(2 != indexes->Count())
sl@0
   153
		{
sl@0
   154
		DEBUG_PRINTF(_L("The index on the decision table is missing!"));
sl@0
   155
		User::Leave(KErrNotFound);
sl@0
   156
		}
sl@0
   157
	CleanupStack::PopAndDestroy(indexes);
sl@0
   158
sl@0
   159
	if(iDatabase.IsDamaged())
sl@0
   160
		{
sl@0
   161
		User::LeaveIfError(iDatabase.Recover());
sl@0
   162
		}
sl@0
   163
	
sl@0
   164
	DEBUG_PRINTF2(_L("%S database file has been opened successfully."), iDbName);
sl@0
   165
	}
sl@0
   166
sl@0
   167
sl@0
   168
void CDecisionDbW::CreateDatabaseL(RFs& aFs)
sl@0
   169
/**
sl@0
   170
	Creates a new, empty store database.
sl@0
   171
	@param aFs	Handle to the file server session
sl@0
   172
 */
sl@0
   173
	{
sl@0
   174
	DEBUG_PRINTF2(_L("%S database is being created."), iDbName);
sl@0
   175
	
sl@0
   176
	if(iStore)
sl@0
   177
		{//if database file exists but the table does not, iStore has already been allocated. 
sl@0
   178
		delete iStore;
sl@0
   179
		iStore = 0;
sl@0
   180
		iDatabase.Close();
sl@0
   181
		}
sl@0
   182
sl@0
   183
	//Create a file store
sl@0
   184
	iStore = CPermanentFileStore::ReplaceL(aFs, *iDbName, EFileRead|EFileWrite);
sl@0
   185
	iStore->SetTypeL(iStore->Layout());
sl@0
   186
	
sl@0
   187
	//Create UPS Decision Database in the file store
sl@0
   188
	TStreamId sId = iDatabase.CreateL(iStore);
sl@0
   189
	iStore->SetRootL(sId);
sl@0
   190
	
sl@0
   191
	//Commit the database creation
sl@0
   192
	iStore->CommitL();
sl@0
   193
	
sl@0
   194
	DEBUG_PRINTF2(_L("%S database has been created successfully."), iDbName);
sl@0
   195
	}
sl@0
   196
sl@0
   197
sl@0
   198
void CDecisionDbW::CreateTableL()
sl@0
   199
/**
sl@0
   200
	Creates the decision table in the decision database.
sl@0
   201
 */
sl@0
   202
	{
sl@0
   203
	DEBUG_PRINTF(_L("The Ups decision table is being created."));
sl@0
   204
	
sl@0
   205
	// Create a table definition
sl@0
   206
	CDbColSet* columns=CDbColSet::NewLC();
sl@0
   207
	
sl@0
   208
	// add the columns to the definition
sl@0
   209
	TDbCol clientSid(KColClientSid,EDbColUint32);
sl@0
   210
	clientSid.iAttributes = TDbCol::ENotNull;				
sl@0
   211
	columns->AddL(clientSid);
sl@0
   212
	
sl@0
   213
	TDbCol evaluatorId(KColEvaluatorId,EDbColUint32);
sl@0
   214
	evaluatorId.iAttributes = TDbCol::ENotNull;				
sl@0
   215
	columns->AddL(evaluatorId);
sl@0
   216
	
sl@0
   217
	TDbCol serviceId(KColServiceId,EDbColUint32);
sl@0
   218
	serviceId.iAttributes=TDbCol::ENotNull;
sl@0
   219
	columns->AddL(serviceId);
sl@0
   220
	
sl@0
   221
	TDbCol serverSid(KColServerSid,EDbColUint32);
sl@0
   222
	serverSid.iAttributes=TDbCol::ENotNull;
sl@0
   223
	columns->AddL(serverSid);
sl@0
   224
	
sl@0
   225
	TDbCol fingerprint(KColFingerprint,EDbColText8,KUpsMaxFingerprintLength );
sl@0
   226
	columns->AddL(fingerprint);
sl@0
   227
	
sl@0
   228
	TDbCol clientEntity(KColClientEntity,EDbColText8,KUpsMaxClientEntityLength);
sl@0
   229
	columns->AddL(clientEntity);
sl@0
   230
	
sl@0
   231
	TDbCol description(KColDescription,EDbColLongText);
sl@0
   232
	columns->AddL(description);
sl@0
   233
	
sl@0
   234
	TDbCol result(KColResult,EDbColInt8);
sl@0
   235
	result.iAttributes=TDbCol::ENotNull;
sl@0
   236
	columns->AddL(result);
sl@0
   237
	
sl@0
   238
	TDbCol evaluatorInfo(KColEvaluatorInfo,EDbColUint32);
sl@0
   239
	columns->AddL(evaluatorInfo);
sl@0
   240
	
sl@0
   241
	TDbCol policyVersion(KColMajorPolicyVersion,EDbColUint16);
sl@0
   242
	policyVersion.iAttributes=TDbCol::ENotNull;
sl@0
   243
	columns->AddL(policyVersion);
sl@0
   244
	
sl@0
   245
	TDbCol recordId(KColRecordId,EDbColUint32);
sl@0
   246
	recordId.iAttributes=TDbCol::ENotNull|TDbCol::EAutoIncrement;
sl@0
   247
	columns->AddL(recordId);
sl@0
   248
	
sl@0
   249
	// Create a table with the table definition
sl@0
   250
	User::LeaveIfError(iDatabase.CreateTable(KDecisionTable,*columns));
sl@0
   251
				
sl@0
   252
	// cleanup the column set
sl@0
   253
	CleanupStack::PopAndDestroy(columns);
sl@0
   254
	
sl@0
   255
	DEBUG_PRINTF(_L("The Ups decision table has been created successfully."));
sl@0
   256
	}
sl@0
   257
sl@0
   258
sl@0
   259
void CDecisionDbW::CreateIndexL()
sl@0
   260
/**
sl@0
   261
	Creates an index on the decision table and makes it unique.
sl@0
   262
 */
sl@0
   263
	{
sl@0
   264
	DEBUG_PRINTF(_L("The Ups decision index is being created on the decision table."));
sl@0
   265
	
sl@0
   266
	// create the index key
sl@0
   267
	CDbKey* key=CDbKey::NewLC();
sl@0
   268
sl@0
   269
	// add the key columns
sl@0
   270
	key->AddL(TDbKeyCol(KColClientSid));
sl@0
   271
	key->AddL(TDbKeyCol(KColEvaluatorId));
sl@0
   272
	key->AddL(TDbKeyCol(KColServiceId));
sl@0
   273
	key->AddL(TDbKeyCol(KColServerSid));
sl@0
   274
	key->AddL(TDbKeyCol(KColFingerprint));
sl@0
   275
	key->AddL(TDbKeyCol(KColClientEntity));
sl@0
   276
	key->AddL(TDbKeyCol(KColMajorPolicyVersion));
sl@0
   277
	
sl@0
   278
	//Make the index key unique
sl@0
   279
	key->MakeUnique();
sl@0
   280
	
sl@0
   281
	// create the primary index
sl@0
   282
	User::LeaveIfError(iDatabase.CreateIndex(KPrimaryIndex,KDecisionTable,*key));
sl@0
   283
	
sl@0
   284
	//Now create the second index on the record id
sl@0
   285
	key->Clear();
sl@0
   286
	// add the record id column
sl@0
   287
	key->AddL(TDbKeyCol(KColRecordId));
sl@0
   288
	key->MakeUnique();
sl@0
   289
	
sl@0
   290
	// create the record id index
sl@0
   291
	User::LeaveIfError(iDatabase.CreateIndex(KRecordIdIndex,KDecisionTable,*key));
sl@0
   292
	
sl@0
   293
	// cleanup the key
sl@0
   294
	CleanupStack::PopAndDestroy(key);
sl@0
   295
	
sl@0
   296
	DEBUG_PRINTF(_L("The Ups decision index has been created successfully."));
sl@0
   297
	}
sl@0
   298
sl@0
   299
sl@0
   300
EXPORT_C void CDecisionDbW::DeleteDatabaseL(RFs& aFs)
sl@0
   301
/**
sl@0
   302
	Delete the decision database completely.
sl@0
   303
	@param aFs	Handle to the file server session
sl@0
   304
 */
sl@0
   305
	{
sl@0
   306
	DEBUG_PRINTF2(_L("%S database is being deleted."),iDbName);
sl@0
   307
	
sl@0
   308
	iDatabase.Close();
sl@0
   309
	delete iStore;
sl@0
   310
	iStore = 0;
sl@0
   311
	User::LeaveIfError(aFs.Delete(*iDbName));
sl@0
   312
	
sl@0
   313
	DEBUG_PRINTF2(_L("%S database has been deleted successfully."),iDbName);
sl@0
   314
	}
sl@0
   315
sl@0
   316
sl@0
   317
void CDecisionDbW::UpdateCurrentRowL(RDbTable& aTable, CDecisionRecord& aRecord)
sl@0
   318
/**
sl@0
   319
	Updates the current row of the rowset by using the values the provided decision record.
sl@0
   320
	
sl@0
   321
	@param aTable  A table object which provides access to table data as a rowset.
sl@0
   322
	@param aRecord A decision record object used to update the current row.
sl@0
   323
 */
sl@0
   324
	{
sl@0
   325
	//Use CDbColSet to set fields
sl@0
   326
	CDbColSet* colSet = aTable.ColSetL();
sl@0
   327
	CleanupStack::PushL(colSet);
sl@0
   328
	
sl@0
   329
	//Set the fields of the empty row
sl@0
   330
	aTable.SetColL(colSet->ColNo(KColClientSid)	 ,(TUint32)aRecord.iClientSid.iId);
sl@0
   331
	aTable.SetColL(colSet->ColNo(KColEvaluatorId),(TUint32)aRecord.iEvaluatorId.iUid);
sl@0
   332
	aTable.SetColL(colSet->ColNo(KColServiceId)  ,(TUint32)aRecord.iServiceId.iUid);
sl@0
   333
	aTable.SetColL(colSet->ColNo(KColServerSid)	 ,(TUint32)aRecord.iServerSid.iId);
sl@0
   334
	
sl@0
   335
	//Fingerprint may be null
sl@0
   336
	if(aRecord.iFingerprint.Length() != 0)
sl@0
   337
		{
sl@0
   338
		aTable.SetColL(colSet->ColNo(KColFingerprint),aRecord.iFingerprint);
sl@0
   339
		}
sl@0
   340
	
sl@0
   341
	//ClientEntity may be null
sl@0
   342
	if(aRecord.iClientEntity.Length() != 0)
sl@0
   343
		{
sl@0
   344
		aTable.SetColL(colSet->ColNo(KColClientEntity),aRecord.iClientEntity);
sl@0
   345
		}
sl@0
   346
	
sl@0
   347
	//Description may be null	
sl@0
   348
	if(aRecord.iDescription.Length() != 0)
sl@0
   349
		{
sl@0
   350
		//A long column is written by using an RDbColStream
sl@0
   351
		RDbColWriteStream str;
sl@0
   352
		TDbColNo col = colSet->ColNo(KColDescription);
sl@0
   353
		
sl@0
   354
		str.OpenLC(aTable,col);
sl@0
   355
		str.WriteL(aRecord.iDescription);
sl@0
   356
		str.Close();
sl@0
   357
		
sl@0
   358
		CleanupStack::PopAndDestroy(&str);
sl@0
   359
		}
sl@0
   360
		
sl@0
   361
	aTable.SetColL(colSet->ColNo(KColResult),aRecord.iResult);
sl@0
   362
	aTable.SetColL(colSet->ColNo(KColEvaluatorInfo),(TUint32)aRecord.iEvaluatorInfo);
sl@0
   363
	aTable.SetColL(colSet->ColNo(KColMajorPolicyVersion),aRecord.iMajorPolicyVersion);
sl@0
   364
	
sl@0
   365
	CleanupStack::PopAndDestroy(colSet);
sl@0
   366
	}
sl@0
   367
sl@0
   368
sl@0
   369
EXPORT_C void CDecisionDbW::CreateDecisionL(CDecisionRecord& aRecord)
sl@0
   370
/**
sl@0
   371
	Inserts a new decision record into the decision database.
sl@0
   372
	
sl@0
   373
	@param aRecord A new decision record
sl@0
   374
 */
sl@0
   375
	{
sl@0
   376
	//Create a database table object
sl@0
   377
	RDbTable dbTable;
sl@0
   378
	User::LeaveIfError(dbTable.Open(iDatabase,KDecisionTable,dbTable.EInsertOnly));
sl@0
   379
	CleanupClosePushL(dbTable);
sl@0
   380
	
sl@0
   381
	//Set the rowset cursor to the beginning position
sl@0
   382
	dbTable.Reset();
sl@0
   383
	
sl@0
   384
	//Insert an empty row into the table
sl@0
   385
	dbTable.InsertL();
sl@0
   386
	
sl@0
   387
	//Set the fields of newly inserted row
sl@0
   388
	UpdateCurrentRowL(dbTable, aRecord);
sl@0
   389
	
sl@0
   390
	//Complete insertion
sl@0
   391
	dbTable.PutL();
sl@0
   392
sl@0
   393
	CleanupStack::Pop(&dbTable);
sl@0
   394
	//Close the rowset
sl@0
   395
	dbTable.Close();	 
sl@0
   396
	}
sl@0
   397
sl@0
   398
sl@0
   399
void CDecisionDbW::PrepareForSearchL(RDbTable& aTable, CDecisionFilter& aFilter, TDbSeekMultiKey<KIndexColumnNumber>& aSeekKey)
sl@0
   400
/**
sl@0
   401
	Opens the provided table object on the decision database and sets the decision index 
sl@0
   402
	as the active index for this table. If successful, the rowset is reset to the beginning.
sl@0
   403
sl@0
   404
	@param aTable  A table object which provides access to table data as a rowset.
sl@0
   405
	@param aFilter A filter object which is used to set the decision index.
sl@0
   406
	@return 	   The key value to lookup in the index.
sl@0
   407
 */
sl@0
   408
	{
sl@0
   409
	User::LeaveIfError(aTable.Open(iDatabase, KDecisionTable, aTable.EUpdatable));
sl@0
   410
	
sl@0
   411
	TUint16 flags = KSetClientSid|KSetEvaluatorId|KSetServiceId|KSetServerSid|KSetFingerprint|KSetClientEntity|KSetMajorPolicyVersion;
sl@0
   412
	
sl@0
   413
	TUint16 combinedFlags = (0x00FF) & (aFilter.iSetFlag[KPosClientSid]   | aFilter.iSetFlag[KPosEvaluatorId] |
sl@0
   414
						     			aFilter.iSetFlag[KPosServiceId]   | aFilter.iSetFlag[KPosServerSid]   |
sl@0
   415
						     			aFilter.iSetFlag[KPosFingerprint] | aFilter.iSetFlag[KPosClientEntity]|
sl@0
   416
						     			aFilter.iSetFlag[KPosMajorPolicyVersion]);
sl@0
   417
sl@0
   418
	//If any of these flags is not set, do not continue
sl@0
   419
	if ((combinedFlags & flags) != flags)
sl@0
   420
		{
sl@0
   421
		DEBUG_PRINTF(_L("The provided filter does not have all required keys to look up a decision."));
sl@0
   422
		User::Leave(KErrUpsMissingArgument);
sl@0
   423
		}
sl@0
   424
	
sl@0
   425
	aSeekKey.Add((TUint)aFilter.iClientSid.iId);
sl@0
   426
	aSeekKey.Add((TUint)aFilter.iEvaluatorId.iUid);
sl@0
   427
	aSeekKey.Add((TUint)aFilter.iServiceId.iUid);
sl@0
   428
	aSeekKey.Add((TUint)aFilter.iServerSid.iId);
sl@0
   429
	aSeekKey.Add(*aFilter.iFingerprint);
sl@0
   430
	aSeekKey.Add(*aFilter.iClientEntity);
sl@0
   431
	aSeekKey.Add(aFilter.iMajorPolicyVersion);
sl@0
   432
			
sl@0
   433
	//Set the primary index
sl@0
   434
	User::LeaveIfError(aTable.SetIndex(KPrimaryIndex));
sl@0
   435
sl@0
   436
	}
sl@0
   437
sl@0
   438
sl@0
   439
EXPORT_C CDecisionRecord* CDecisionDbW::GetDecisionL(CDecisionFilter& aFilter)
sl@0
   440
/**
sl@0
   441
	Gets a decision record from the decision database. The functions returns the first matched
sl@0
   442
	record. All the methods of the filter object except the client entity should be supplied to 
sl@0
   443
	get the intended decision record. If any other attribute of the filter object is missing, 
sl@0
   444
	either no decision might be found or a wrong decision may be retrieved
sl@0
   445
	
sl@0
   446
	@param aFilter A filter object whose client id, policy evaluator id, service id,
sl@0
   447
	 			   server id, fingerprint (and client entity) attributes are set.
sl@0
   448
 */
sl@0
   449
	{
sl@0
   450
	//Define a database table object handle
sl@0
   451
	RDbTable dbTable;
sl@0
   452
	CleanupClosePushL(dbTable);
sl@0
   453
	
sl@0
   454
	//Open the database table object and prepares it for searching
sl@0
   455
	TDbSeekMultiKey<KIndexColumnNumber> seekKey;
sl@0
   456
	PrepareForSearchL(dbTable,aFilter,seekKey);
sl@0
   457
	
sl@0
   458
	//Define the decision record that will be returned
sl@0
   459
	CDecisionRecord* retRecord(0);
sl@0
   460
	
sl@0
   461
	if(dbTable.SeekL(seekKey))
sl@0
   462
		{
sl@0
   463
		//Result found
sl@0
   464
		CDbColSet* colSet = dbTable.ColSetL();
sl@0
   465
		CleanupStack::PushL(colSet);
sl@0
   466
		
sl@0
   467
		dbTable.GetL();
sl@0
   468
		
sl@0
   469
		retRecord = CDecisionView::GenerateRecordL(dbTable,colSet);
sl@0
   470
		
sl@0
   471
		CleanupStack::PopAndDestroy(colSet);		
sl@0
   472
		}
sl@0
   473
sl@0
   474
	CleanupStack::PopAndDestroy(&dbTable);
sl@0
   475
	
sl@0
   476
	return retRecord;
sl@0
   477
	}
sl@0
   478
sl@0
   479
sl@0
   480
EXPORT_C TBool CDecisionDbW::UpdateDecisionL(CDecisionFilter& aFilter, CDecisionRecord& aNewRecord)
sl@0
   481
	{
sl@0
   482
	//Define a database table object handle
sl@0
   483
	RDbTable dbTable;
sl@0
   484
	CleanupClosePushL(dbTable);
sl@0
   485
	
sl@0
   486
	//Open the database table object and prepares it for searching
sl@0
   487
	TDbSeekMultiKey<KIndexColumnNumber> seekKey;
sl@0
   488
	PrepareForSearchL(dbTable,aFilter,seekKey);
sl@0
   489
	
sl@0
   490
	TBool retValue = ETrue; //return value
sl@0
   491
	
sl@0
   492
	if(dbTable.SeekL(seekKey))
sl@0
   493
		{
sl@0
   494
		//Get the current row
sl@0
   495
		dbTable.GetL();
sl@0
   496
		//Prepare it for update
sl@0
   497
		dbTable.UpdateL();
sl@0
   498
		//Set the new values
sl@0
   499
		UpdateCurrentRowL(dbTable, aNewRecord);
sl@0
   500
		//Commit the update
sl@0
   501
		dbTable.PutL();
sl@0
   502
		}
sl@0
   503
	else
sl@0
   504
		{
sl@0
   505
		retValue = EFalse;
sl@0
   506
		}
sl@0
   507
	
sl@0
   508
	CleanupStack::PopAndDestroy(&dbTable);
sl@0
   509
	
sl@0
   510
	return retValue;
sl@0
   511
	}
sl@0
   512
	
sl@0
   513
sl@0
   514
void CDecisionDbW::DoRemoveDecisionL(CDecisionFilter& aFilter)
sl@0
   515
/**
sl@0
   516
	Deletes a set of records from the decision database. This function is called 
sl@0
   517
	by RemoveDecisionsL in a loop to be able to catch and repair index corruptions.
sl@0
   518
	
sl@0
   519
	@param aFilter A filter object
sl@0
   520
 */
sl@0
   521
	{
sl@0
   522
	//Create the SQL statement
sl@0
   523
	RBuf sqlStatement;
sl@0
   524
	CreateSqlStatementLC(aFilter, sqlStatement);
sl@0
   525
						
sl@0
   526
	RDbView dbView;
sl@0
   527
	CleanupClosePushL(dbView);
sl@0
   528
	
sl@0
   529
	User::LeaveIfError(dbView.Prepare(iDatabase,TDbQuery(sqlStatement),TDbWindow::EUnlimited));
sl@0
   530
	User::LeaveIfError(dbView.EvaluateAll());
sl@0
   531
sl@0
   532
	//Begin the delete transaction and lock the database
sl@0
   533
	User::LeaveIfError(iDatabase.Begin());	
sl@0
   534
		
sl@0
   535
	while(dbView.NextL())
sl@0
   536
		{
sl@0
   537
		dbView.DeleteL();
sl@0
   538
		}
sl@0
   539
			
sl@0
   540
	CleanupStack::PopAndDestroy(&dbView);		
sl@0
   541
	CleanupStack::PopAndDestroy(&sqlStatement);
sl@0
   542
	
sl@0
   543
	//Release the lock
sl@0
   544
	TInt result = iDatabase.Commit();
sl@0
   545
	if(KErrNone != result)
sl@0
   546
		{
sl@0
   547
		DEBUG_PRINTF2(_L("Removing a decision has returned with %d. Rollback is now in proggress."),result);
sl@0
   548
		iDatabase.Rollback();
sl@0
   549
		User::Leave(result);
sl@0
   550
		}
sl@0
   551
	}
sl@0
   552
sl@0
   553
EXPORT_C void CDecisionDbW::RemoveDecisionsL(CDecisionFilter& aFilter)
sl@0
   554
/**
sl@0
   555
	Deletes a set of records from the decision database. It is possible to delete a specific
sl@0
   556
	decision record or a set of records based on a given filter. While this function is in
sl@0
   557
	progress, the database is locked not to lead to an inconsistent data retrieving. If there
sl@0
   558
	is any index corruption in the decision able, it is tried to be repaired automatically.
sl@0
   559
	
sl@0
   560
	@param aFilter A filter object
sl@0
   561
 */
sl@0
   562
	{
sl@0
   563
	TInt loopCount=1;
sl@0
   564
	TInt error;
sl@0
   565
	do
sl@0
   566
		{
sl@0
   567
		++loopCount;
sl@0
   568
		TRAP(error,DoRemoveDecisionL(aFilter));
sl@0
   569
		if(error == KErrCorrupt)
sl@0
   570
			{
sl@0
   571
			DEBUG_PRINTF2(_L("The database is corrupted and being recovered. Try %d"),loopCount);
sl@0
   572
			error = iDatabase.Recover(); //Recover() may fail, so update error
sl@0
   573
			}
sl@0
   574
		}while(error==KErrCorrupt && loopCount<2);
sl@0
   575
		
sl@0
   576
	User::LeaveIfError(error);
sl@0
   577
	}
sl@0
   578
sl@0
   579
sl@0
   580
EXPORT_C CDecisionDbCompactor *CDecisionDbW::PrepareCompactionLC()
sl@0
   581
/**
sl@0
   582
	Creates a database compaction object to perform asynchronous compaction on the database.
sl@0
   583
	
sl@0
   584
	@return A pointer to the newly created database compaction object
sl@0
   585
			The pointer is also put onto the cleanup stack.
sl@0
   586
 */
sl@0
   587
	{
sl@0
   588
	DEBUG_PRINTF(_L("The Ups database is being compacted."));
sl@0
   589
	CDecisionDbCompactor *compactor = CDecisionDbCompactor::NewLC();
sl@0
   590
	User::LeaveIfError(compactor->iDbIncremental.Compact(iDatabase,compactor->iStep()));
sl@0
   591
	return compactor;
sl@0
   592
	}
sl@0
   593