1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/authorisation/userpromptservice/database/source/upsdbw.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,593 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +* Implements a writable interface for UPS Database.
1.19 +*
1.20 +*/
1.21 +
1.22 +
1.23 +/**
1.24 + @file
1.25 + @internalTechnology
1.26 + @released
1.27 +*/
1.28 +
1.29 +#include "upsdbw.h"
1.30 +#include "upscommon.h"
1.31 +
1.32 +using namespace UserPromptService;
1.33 +
1.34 +CDecisionDbW::CDecisionDbW()
1.35 +/**
1.36 + Constructor for writable decision database object
1.37 + */
1.38 + {
1.39 +
1.40 + }
1.41 +
1.42 +
1.43 +CDecisionDbW::~CDecisionDbW()
1.44 +/**
1.45 + Destructor for writable decision database object
1.46 + */
1.47 + {
1.48 + iDatabase.Close();
1.49 + delete iDbName;
1.50 + delete iStore;
1.51 + }
1.52 +
1.53 +
1.54 +EXPORT_C CDecisionDbW* CDecisionDbW::NewL(const TDesC& aDbName, RFs& aFs)
1.55 +/**
1.56 + Creates a writable decision database object and connects to the database.
1.57 + If the database does not exist or is corrupted, a new decision database is created.
1.58 + The function leaves, if creation of the object or connection to the database fail.
1.59 +
1.60 + @param aDbName The path of the decision database
1.61 + @param aFs Handle to the file server session
1.62 +
1.63 + @return A pointer to the newly allocated database object, if creation and connection are successful.
1.64 + */
1.65 + {
1.66 + CDecisionDbW* self = CDecisionDbW::NewLC(aDbName, aFs);
1.67 + CleanupStack::Pop(self);
1.68 + return self;
1.69 + }
1.70 +
1.71 +
1.72 +EXPORT_C CDecisionDbW* CDecisionDbW::NewLC(const TDesC& aDbName, RFs& aFs)
1.73 +/**
1.74 + Creates a writable decision database object and connects to the database.
1.75 + If the database does not exist or is corrupted, a new decision database is created.
1.76 + The function leaves, if creation of the object or connection to the database fail.
1.77 +
1.78 + @param aDbName The path of the decision database
1.79 + param aFs Handle to the file server session
1.80 +
1.81 + @return A pointer to the newly allocated database object, if creation and connection
1.82 + are successful. The pointer is also put onto the cleanup stack.
1.83 + */
1.84 + {
1.85 + CDecisionDbW* self = new (ELeave) CDecisionDbW();
1.86 + CleanupStack::PushL(self);
1.87 + self->ConstructL(aDbName, aFs);
1.88 + return self;
1.89 + }
1.90 +
1.91 +
1.92 +void CDecisionDbW::ConstructL(const TDesC& aDbName, RFs& aFs)
1.93 +/**
1.94 + Second phase constructor for the decision database object. Connects to the decision database.
1.95 + If the database does not existed or is corrupted, creates a new one. The function leaves,
1.96 + if both database connection and creation fail.
1.97 +
1.98 + @param aDbName The path of the decision database
1.99 + @param aFs Handle to the file server session
1.100 + */
1.101 + {
1.102 + //Construct the name of UPS decision database
1.103 + iDbName = aDbName.AllocL();
1.104 +
1.105 + //First try to open the decision database
1.106 + TRAPD(error,OpenDatabaseL(aFs));
1.107 +
1.108 + if((error == KErrNoMemory) || (error == KErrDiskFull))
1.109 + {
1.110 + User::Leave(error);
1.111 + }
1.112 +
1.113 + // Makes sure that DB file is writable. (DEF122590)
1.114 + aFs.SetAtt(iDbName->Des(),0, KEntryAttReadOnly);
1.115 +
1.116 + if(error != KErrNone)
1.117 + {
1.118 + DEBUG_PRINTF2(_L("%S database file does not exist or is corrupted."), iDbName);
1.119 + //The decision database does not exist or is corrupted, create a new one
1.120 + CreateDatabaseL(aFs);
1.121 +
1.122 + //Create a decision table in the decision database
1.123 + CreateTableL();
1.124 +
1.125 + //Create an index on the decision table
1.126 + CreateIndexL();
1.127 + }
1.128 + }
1.129 +
1.130 +
1.131 +void CDecisionDbW::OpenDatabaseL(RFs& aFs)
1.132 +/**
1.133 + Opens the decision database.
1.134 + @param aFs Handle to the file server session
1.135 + */
1.136 + {
1.137 + DEBUG_PRINTF2(_L("%S database file is being opened."), iDbName);
1.138 +
1.139 + iStore = CPermanentFileStore::OpenL(aFs, *iDbName, EFileRead|EFileWrite);
1.140 + iDatabase.OpenL(iStore, iStore->Root());
1.141 +
1.142 + //Database does exist. However, make sure that the decision table also exists
1.143 + CDbTableNames *tables = iDatabase.TableNamesL();
1.144 + CleanupStack::PushL(tables);
1.145 + if(1 != tables->Count())
1.146 + {
1.147 + DEBUG_PRINTF(_L("The decision table could not be found in the database file!"));
1.148 + User::Leave(KErrNotFound);
1.149 + }
1.150 + CleanupStack::PopAndDestroy(tables);
1.151 +
1.152 + //OK. The decision table does exist. What about the decision index?
1.153 + CDbIndexNames *indexes = iDatabase.IndexNamesL(KDecisionTable);
1.154 + CleanupStack::PushL(indexes);
1.155 + if(2 != indexes->Count())
1.156 + {
1.157 + DEBUG_PRINTF(_L("The index on the decision table is missing!"));
1.158 + User::Leave(KErrNotFound);
1.159 + }
1.160 + CleanupStack::PopAndDestroy(indexes);
1.161 +
1.162 + if(iDatabase.IsDamaged())
1.163 + {
1.164 + User::LeaveIfError(iDatabase.Recover());
1.165 + }
1.166 +
1.167 + DEBUG_PRINTF2(_L("%S database file has been opened successfully."), iDbName);
1.168 + }
1.169 +
1.170 +
1.171 +void CDecisionDbW::CreateDatabaseL(RFs& aFs)
1.172 +/**
1.173 + Creates a new, empty store database.
1.174 + @param aFs Handle to the file server session
1.175 + */
1.176 + {
1.177 + DEBUG_PRINTF2(_L("%S database is being created."), iDbName);
1.178 +
1.179 + if(iStore)
1.180 + {//if database file exists but the table does not, iStore has already been allocated.
1.181 + delete iStore;
1.182 + iStore = 0;
1.183 + iDatabase.Close();
1.184 + }
1.185 +
1.186 + //Create a file store
1.187 + iStore = CPermanentFileStore::ReplaceL(aFs, *iDbName, EFileRead|EFileWrite);
1.188 + iStore->SetTypeL(iStore->Layout());
1.189 +
1.190 + //Create UPS Decision Database in the file store
1.191 + TStreamId sId = iDatabase.CreateL(iStore);
1.192 + iStore->SetRootL(sId);
1.193 +
1.194 + //Commit the database creation
1.195 + iStore->CommitL();
1.196 +
1.197 + DEBUG_PRINTF2(_L("%S database has been created successfully."), iDbName);
1.198 + }
1.199 +
1.200 +
1.201 +void CDecisionDbW::CreateTableL()
1.202 +/**
1.203 + Creates the decision table in the decision database.
1.204 + */
1.205 + {
1.206 + DEBUG_PRINTF(_L("The Ups decision table is being created."));
1.207 +
1.208 + // Create a table definition
1.209 + CDbColSet* columns=CDbColSet::NewLC();
1.210 +
1.211 + // add the columns to the definition
1.212 + TDbCol clientSid(KColClientSid,EDbColUint32);
1.213 + clientSid.iAttributes = TDbCol::ENotNull;
1.214 + columns->AddL(clientSid);
1.215 +
1.216 + TDbCol evaluatorId(KColEvaluatorId,EDbColUint32);
1.217 + evaluatorId.iAttributes = TDbCol::ENotNull;
1.218 + columns->AddL(evaluatorId);
1.219 +
1.220 + TDbCol serviceId(KColServiceId,EDbColUint32);
1.221 + serviceId.iAttributes=TDbCol::ENotNull;
1.222 + columns->AddL(serviceId);
1.223 +
1.224 + TDbCol serverSid(KColServerSid,EDbColUint32);
1.225 + serverSid.iAttributes=TDbCol::ENotNull;
1.226 + columns->AddL(serverSid);
1.227 +
1.228 + TDbCol fingerprint(KColFingerprint,EDbColText8,KUpsMaxFingerprintLength );
1.229 + columns->AddL(fingerprint);
1.230 +
1.231 + TDbCol clientEntity(KColClientEntity,EDbColText8,KUpsMaxClientEntityLength);
1.232 + columns->AddL(clientEntity);
1.233 +
1.234 + TDbCol description(KColDescription,EDbColLongText);
1.235 + columns->AddL(description);
1.236 +
1.237 + TDbCol result(KColResult,EDbColInt8);
1.238 + result.iAttributes=TDbCol::ENotNull;
1.239 + columns->AddL(result);
1.240 +
1.241 + TDbCol evaluatorInfo(KColEvaluatorInfo,EDbColUint32);
1.242 + columns->AddL(evaluatorInfo);
1.243 +
1.244 + TDbCol policyVersion(KColMajorPolicyVersion,EDbColUint16);
1.245 + policyVersion.iAttributes=TDbCol::ENotNull;
1.246 + columns->AddL(policyVersion);
1.247 +
1.248 + TDbCol recordId(KColRecordId,EDbColUint32);
1.249 + recordId.iAttributes=TDbCol::ENotNull|TDbCol::EAutoIncrement;
1.250 + columns->AddL(recordId);
1.251 +
1.252 + // Create a table with the table definition
1.253 + User::LeaveIfError(iDatabase.CreateTable(KDecisionTable,*columns));
1.254 +
1.255 + // cleanup the column set
1.256 + CleanupStack::PopAndDestroy(columns);
1.257 +
1.258 + DEBUG_PRINTF(_L("The Ups decision table has been created successfully."));
1.259 + }
1.260 +
1.261 +
1.262 +void CDecisionDbW::CreateIndexL()
1.263 +/**
1.264 + Creates an index on the decision table and makes it unique.
1.265 + */
1.266 + {
1.267 + DEBUG_PRINTF(_L("The Ups decision index is being created on the decision table."));
1.268 +
1.269 + // create the index key
1.270 + CDbKey* key=CDbKey::NewLC();
1.271 +
1.272 + // add the key columns
1.273 + key->AddL(TDbKeyCol(KColClientSid));
1.274 + key->AddL(TDbKeyCol(KColEvaluatorId));
1.275 + key->AddL(TDbKeyCol(KColServiceId));
1.276 + key->AddL(TDbKeyCol(KColServerSid));
1.277 + key->AddL(TDbKeyCol(KColFingerprint));
1.278 + key->AddL(TDbKeyCol(KColClientEntity));
1.279 + key->AddL(TDbKeyCol(KColMajorPolicyVersion));
1.280 +
1.281 + //Make the index key unique
1.282 + key->MakeUnique();
1.283 +
1.284 + // create the primary index
1.285 + User::LeaveIfError(iDatabase.CreateIndex(KPrimaryIndex,KDecisionTable,*key));
1.286 +
1.287 + //Now create the second index on the record id
1.288 + key->Clear();
1.289 + // add the record id column
1.290 + key->AddL(TDbKeyCol(KColRecordId));
1.291 + key->MakeUnique();
1.292 +
1.293 + // create the record id index
1.294 + User::LeaveIfError(iDatabase.CreateIndex(KRecordIdIndex,KDecisionTable,*key));
1.295 +
1.296 + // cleanup the key
1.297 + CleanupStack::PopAndDestroy(key);
1.298 +
1.299 + DEBUG_PRINTF(_L("The Ups decision index has been created successfully."));
1.300 + }
1.301 +
1.302 +
1.303 +EXPORT_C void CDecisionDbW::DeleteDatabaseL(RFs& aFs)
1.304 +/**
1.305 + Delete the decision database completely.
1.306 + @param aFs Handle to the file server session
1.307 + */
1.308 + {
1.309 + DEBUG_PRINTF2(_L("%S database is being deleted."),iDbName);
1.310 +
1.311 + iDatabase.Close();
1.312 + delete iStore;
1.313 + iStore = 0;
1.314 + User::LeaveIfError(aFs.Delete(*iDbName));
1.315 +
1.316 + DEBUG_PRINTF2(_L("%S database has been deleted successfully."),iDbName);
1.317 + }
1.318 +
1.319 +
1.320 +void CDecisionDbW::UpdateCurrentRowL(RDbTable& aTable, CDecisionRecord& aRecord)
1.321 +/**
1.322 + Updates the current row of the rowset by using the values the provided decision record.
1.323 +
1.324 + @param aTable A table object which provides access to table data as a rowset.
1.325 + @param aRecord A decision record object used to update the current row.
1.326 + */
1.327 + {
1.328 + //Use CDbColSet to set fields
1.329 + CDbColSet* colSet = aTable.ColSetL();
1.330 + CleanupStack::PushL(colSet);
1.331 +
1.332 + //Set the fields of the empty row
1.333 + aTable.SetColL(colSet->ColNo(KColClientSid) ,(TUint32)aRecord.iClientSid.iId);
1.334 + aTable.SetColL(colSet->ColNo(KColEvaluatorId),(TUint32)aRecord.iEvaluatorId.iUid);
1.335 + aTable.SetColL(colSet->ColNo(KColServiceId) ,(TUint32)aRecord.iServiceId.iUid);
1.336 + aTable.SetColL(colSet->ColNo(KColServerSid) ,(TUint32)aRecord.iServerSid.iId);
1.337 +
1.338 + //Fingerprint may be null
1.339 + if(aRecord.iFingerprint.Length() != 0)
1.340 + {
1.341 + aTable.SetColL(colSet->ColNo(KColFingerprint),aRecord.iFingerprint);
1.342 + }
1.343 +
1.344 + //ClientEntity may be null
1.345 + if(aRecord.iClientEntity.Length() != 0)
1.346 + {
1.347 + aTable.SetColL(colSet->ColNo(KColClientEntity),aRecord.iClientEntity);
1.348 + }
1.349 +
1.350 + //Description may be null
1.351 + if(aRecord.iDescription.Length() != 0)
1.352 + {
1.353 + //A long column is written by using an RDbColStream
1.354 + RDbColWriteStream str;
1.355 + TDbColNo col = colSet->ColNo(KColDescription);
1.356 +
1.357 + str.OpenLC(aTable,col);
1.358 + str.WriteL(aRecord.iDescription);
1.359 + str.Close();
1.360 +
1.361 + CleanupStack::PopAndDestroy(&str);
1.362 + }
1.363 +
1.364 + aTable.SetColL(colSet->ColNo(KColResult),aRecord.iResult);
1.365 + aTable.SetColL(colSet->ColNo(KColEvaluatorInfo),(TUint32)aRecord.iEvaluatorInfo);
1.366 + aTable.SetColL(colSet->ColNo(KColMajorPolicyVersion),aRecord.iMajorPolicyVersion);
1.367 +
1.368 + CleanupStack::PopAndDestroy(colSet);
1.369 + }
1.370 +
1.371 +
1.372 +EXPORT_C void CDecisionDbW::CreateDecisionL(CDecisionRecord& aRecord)
1.373 +/**
1.374 + Inserts a new decision record into the decision database.
1.375 +
1.376 + @param aRecord A new decision record
1.377 + */
1.378 + {
1.379 + //Create a database table object
1.380 + RDbTable dbTable;
1.381 + User::LeaveIfError(dbTable.Open(iDatabase,KDecisionTable,dbTable.EInsertOnly));
1.382 + CleanupClosePushL(dbTable);
1.383 +
1.384 + //Set the rowset cursor to the beginning position
1.385 + dbTable.Reset();
1.386 +
1.387 + //Insert an empty row into the table
1.388 + dbTable.InsertL();
1.389 +
1.390 + //Set the fields of newly inserted row
1.391 + UpdateCurrentRowL(dbTable, aRecord);
1.392 +
1.393 + //Complete insertion
1.394 + dbTable.PutL();
1.395 +
1.396 + CleanupStack::Pop(&dbTable);
1.397 + //Close the rowset
1.398 + dbTable.Close();
1.399 + }
1.400 +
1.401 +
1.402 +void CDecisionDbW::PrepareForSearchL(RDbTable& aTable, CDecisionFilter& aFilter, TDbSeekMultiKey<KIndexColumnNumber>& aSeekKey)
1.403 +/**
1.404 + Opens the provided table object on the decision database and sets the decision index
1.405 + as the active index for this table. If successful, the rowset is reset to the beginning.
1.406 +
1.407 + @param aTable A table object which provides access to table data as a rowset.
1.408 + @param aFilter A filter object which is used to set the decision index.
1.409 + @return The key value to lookup in the index.
1.410 + */
1.411 + {
1.412 + User::LeaveIfError(aTable.Open(iDatabase, KDecisionTable, aTable.EUpdatable));
1.413 +
1.414 + TUint16 flags = KSetClientSid|KSetEvaluatorId|KSetServiceId|KSetServerSid|KSetFingerprint|KSetClientEntity|KSetMajorPolicyVersion;
1.415 +
1.416 + TUint16 combinedFlags = (0x00FF) & (aFilter.iSetFlag[KPosClientSid] | aFilter.iSetFlag[KPosEvaluatorId] |
1.417 + aFilter.iSetFlag[KPosServiceId] | aFilter.iSetFlag[KPosServerSid] |
1.418 + aFilter.iSetFlag[KPosFingerprint] | aFilter.iSetFlag[KPosClientEntity]|
1.419 + aFilter.iSetFlag[KPosMajorPolicyVersion]);
1.420 +
1.421 + //If any of these flags is not set, do not continue
1.422 + if ((combinedFlags & flags) != flags)
1.423 + {
1.424 + DEBUG_PRINTF(_L("The provided filter does not have all required keys to look up a decision."));
1.425 + User::Leave(KErrUpsMissingArgument);
1.426 + }
1.427 +
1.428 + aSeekKey.Add((TUint)aFilter.iClientSid.iId);
1.429 + aSeekKey.Add((TUint)aFilter.iEvaluatorId.iUid);
1.430 + aSeekKey.Add((TUint)aFilter.iServiceId.iUid);
1.431 + aSeekKey.Add((TUint)aFilter.iServerSid.iId);
1.432 + aSeekKey.Add(*aFilter.iFingerprint);
1.433 + aSeekKey.Add(*aFilter.iClientEntity);
1.434 + aSeekKey.Add(aFilter.iMajorPolicyVersion);
1.435 +
1.436 + //Set the primary index
1.437 + User::LeaveIfError(aTable.SetIndex(KPrimaryIndex));
1.438 +
1.439 + }
1.440 +
1.441 +
1.442 +EXPORT_C CDecisionRecord* CDecisionDbW::GetDecisionL(CDecisionFilter& aFilter)
1.443 +/**
1.444 + Gets a decision record from the decision database. The functions returns the first matched
1.445 + record. All the methods of the filter object except the client entity should be supplied to
1.446 + get the intended decision record. If any other attribute of the filter object is missing,
1.447 + either no decision might be found or a wrong decision may be retrieved
1.448 +
1.449 + @param aFilter A filter object whose client id, policy evaluator id, service id,
1.450 + server id, fingerprint (and client entity) attributes are set.
1.451 + */
1.452 + {
1.453 + //Define a database table object handle
1.454 + RDbTable dbTable;
1.455 + CleanupClosePushL(dbTable);
1.456 +
1.457 + //Open the database table object and prepares it for searching
1.458 + TDbSeekMultiKey<KIndexColumnNumber> seekKey;
1.459 + PrepareForSearchL(dbTable,aFilter,seekKey);
1.460 +
1.461 + //Define the decision record that will be returned
1.462 + CDecisionRecord* retRecord(0);
1.463 +
1.464 + if(dbTable.SeekL(seekKey))
1.465 + {
1.466 + //Result found
1.467 + CDbColSet* colSet = dbTable.ColSetL();
1.468 + CleanupStack::PushL(colSet);
1.469 +
1.470 + dbTable.GetL();
1.471 +
1.472 + retRecord = CDecisionView::GenerateRecordL(dbTable,colSet);
1.473 +
1.474 + CleanupStack::PopAndDestroy(colSet);
1.475 + }
1.476 +
1.477 + CleanupStack::PopAndDestroy(&dbTable);
1.478 +
1.479 + return retRecord;
1.480 + }
1.481 +
1.482 +
1.483 +EXPORT_C TBool CDecisionDbW::UpdateDecisionL(CDecisionFilter& aFilter, CDecisionRecord& aNewRecord)
1.484 + {
1.485 + //Define a database table object handle
1.486 + RDbTable dbTable;
1.487 + CleanupClosePushL(dbTable);
1.488 +
1.489 + //Open the database table object and prepares it for searching
1.490 + TDbSeekMultiKey<KIndexColumnNumber> seekKey;
1.491 + PrepareForSearchL(dbTable,aFilter,seekKey);
1.492 +
1.493 + TBool retValue = ETrue; //return value
1.494 +
1.495 + if(dbTable.SeekL(seekKey))
1.496 + {
1.497 + //Get the current row
1.498 + dbTable.GetL();
1.499 + //Prepare it for update
1.500 + dbTable.UpdateL();
1.501 + //Set the new values
1.502 + UpdateCurrentRowL(dbTable, aNewRecord);
1.503 + //Commit the update
1.504 + dbTable.PutL();
1.505 + }
1.506 + else
1.507 + {
1.508 + retValue = EFalse;
1.509 + }
1.510 +
1.511 + CleanupStack::PopAndDestroy(&dbTable);
1.512 +
1.513 + return retValue;
1.514 + }
1.515 +
1.516 +
1.517 +void CDecisionDbW::DoRemoveDecisionL(CDecisionFilter& aFilter)
1.518 +/**
1.519 + Deletes a set of records from the decision database. This function is called
1.520 + by RemoveDecisionsL in a loop to be able to catch and repair index corruptions.
1.521 +
1.522 + @param aFilter A filter object
1.523 + */
1.524 + {
1.525 + //Create the SQL statement
1.526 + RBuf sqlStatement;
1.527 + CreateSqlStatementLC(aFilter, sqlStatement);
1.528 +
1.529 + RDbView dbView;
1.530 + CleanupClosePushL(dbView);
1.531 +
1.532 + User::LeaveIfError(dbView.Prepare(iDatabase,TDbQuery(sqlStatement),TDbWindow::EUnlimited));
1.533 + User::LeaveIfError(dbView.EvaluateAll());
1.534 +
1.535 + //Begin the delete transaction and lock the database
1.536 + User::LeaveIfError(iDatabase.Begin());
1.537 +
1.538 + while(dbView.NextL())
1.539 + {
1.540 + dbView.DeleteL();
1.541 + }
1.542 +
1.543 + CleanupStack::PopAndDestroy(&dbView);
1.544 + CleanupStack::PopAndDestroy(&sqlStatement);
1.545 +
1.546 + //Release the lock
1.547 + TInt result = iDatabase.Commit();
1.548 + if(KErrNone != result)
1.549 + {
1.550 + DEBUG_PRINTF2(_L("Removing a decision has returned with %d. Rollback is now in proggress."),result);
1.551 + iDatabase.Rollback();
1.552 + User::Leave(result);
1.553 + }
1.554 + }
1.555 +
1.556 +EXPORT_C void CDecisionDbW::RemoveDecisionsL(CDecisionFilter& aFilter)
1.557 +/**
1.558 + Deletes a set of records from the decision database. It is possible to delete a specific
1.559 + decision record or a set of records based on a given filter. While this function is in
1.560 + progress, the database is locked not to lead to an inconsistent data retrieving. If there
1.561 + is any index corruption in the decision able, it is tried to be repaired automatically.
1.562 +
1.563 + @param aFilter A filter object
1.564 + */
1.565 + {
1.566 + TInt loopCount=1;
1.567 + TInt error;
1.568 + do
1.569 + {
1.570 + ++loopCount;
1.571 + TRAP(error,DoRemoveDecisionL(aFilter));
1.572 + if(error == KErrCorrupt)
1.573 + {
1.574 + DEBUG_PRINTF2(_L("The database is corrupted and being recovered. Try %d"),loopCount);
1.575 + error = iDatabase.Recover(); //Recover() may fail, so update error
1.576 + }
1.577 + }while(error==KErrCorrupt && loopCount<2);
1.578 +
1.579 + User::LeaveIfError(error);
1.580 + }
1.581 +
1.582 +
1.583 +EXPORT_C CDecisionDbCompactor *CDecisionDbW::PrepareCompactionLC()
1.584 +/**
1.585 + Creates a database compaction object to perform asynchronous compaction on the database.
1.586 +
1.587 + @return A pointer to the newly created database compaction object
1.588 + The pointer is also put onto the cleanup stack.
1.589 + */
1.590 + {
1.591 + DEBUG_PRINTF(_L("The Ups database is being compacted."));
1.592 + CDecisionDbCompactor *compactor = CDecisionDbCompactor::NewLC();
1.593 + User::LeaveIfError(compactor->iDbIncremental.Compact(iDatabase,compactor->iStep()));
1.594 + return compactor;
1.595 + }
1.596 +