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