1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/dbms/pcdbms/ustor/US_DBS.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,546 @@
1.4 +// Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include "US_STD.H"
1.20 +#include "U32STD_DBMS.H"
1.21 +
1.22 +// Class CDbStoreDatabase::CCompactor
1.23 +
1.24 +NONSHARABLE_CLASS(CDbStoreDatabase::CCompactor) : public CDbStoreDatabase::CStepper
1.25 + {
1.26 +public:
1.27 + static CCompactor* NewL(CDbDatabase::TUtility aType, CStreamStore& aStore,
1.28 + TInt& aReclaim, TInt& aStep);
1.29 + ~CCompactor();
1.30 +private:
1.31 + inline CCompactor(TInt& aReclaim);
1.32 +// from CStepper
1.33 + TInt StepL(TInt aStep);
1.34 +private:
1.35 + RStoreReclaim iReclaimer;
1.36 + TInt& iReclaim;
1.37 + };
1.38 +
1.39 +inline CDbStoreDatabase::CCompactor::CCompactor(TInt& aReclaim)
1.40 + :iReclaim(aReclaim)
1.41 + {
1.42 + }
1.43 +
1.44 +CDbStoreDatabase::CCompactor* CDbStoreDatabase::CCompactor::NewL(CDbDatabase::TUtility aType,
1.45 + CStreamStore& aStore,
1.46 + TInt& aReclaim,TInt& aStep)
1.47 + {
1.48 + CCompactor* self=new(ELeave) CCompactor(aReclaim);
1.49 + CleanupStack::PushL(self);
1.50 + if (aType==CDbDatabase::ECompact)
1.51 + self->iReclaimer.CompactL(aStore,aStep);
1.52 + else
1.53 + self->iReclaimer.OpenL(aStore,aStep);
1.54 + CleanupStack::Pop();
1.55 + return self;
1.56 + }
1.57 +
1.58 +CDbStoreDatabase::CCompactor::~CCompactor()
1.59 + {
1.60 + iReclaimer.Close();
1.61 + }
1.62 +
1.63 +//
1.64 +// Single step the compactor
1.65 +// We cannot deal with the "in use" scenario as we could end up locking out forever
1.66 +// that has to be left to clients using the RDbIncremental interface
1.67 +//
1.68 +TInt CDbStoreDatabase::CCompactor::StepL(TInt aStep)
1.69 + {
1.70 + iReclaimer.NextL(aStep);
1.71 + if (aStep==0)
1.72 + {
1.73 + iReclaim=iReclaimer.Available();
1.74 + iReclaimer.Close();
1.75 + }
1.76 + return aStep;
1.77 + }
1.78 +
1.79 +
1.80 +// Class CDbStoreDatabase
1.81 +
1.82 +EXPORT_C CDbStoreDatabase::CDbStoreDatabase()
1.83 + :iReclaim(KErrGeneral)
1.84 + {
1.85 + }
1.86 +
1.87 +//
1.88 +// Create a StoreDatabase object. This type shares the store
1.89 +//
1.90 +CDbStoreDatabase* CDbStoreDatabase::NewLC(CStreamStore* aStore)
1.91 + {
1.92 + __ASSERT(aStore);
1.93 + CDbStoreDatabase* self=new(ELeave) CDbStoreDatabase;
1.94 + CleanupStack::PushL(self);
1.95 + self->iStore=aStore;
1.96 + self->iSharedStore=1;
1.97 + return self;
1.98 + }
1.99 +
1.100 +
1.101 +//SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
1.102 +CDbDatabase* CDbStoreDatabase::CreateL(CStreamStore* aStore,TStreamId& aStreamId)
1.103 + {
1.104 + CDbStoreDatabase* self=NewLC(aStore);
1.105 + aStreamId=self->ConstructL();
1.106 + CDbDatabase* db=self->InterfaceL();
1.107 + CleanupStack::Pop(); // self
1.108 + return db;
1.109 + }
1.110 +
1.111 +// SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
1.112 +// Phase 2 construction for creating a new database
1.113 +// Initialise a new database object, creating the required persistent structure
1.114 +//
1.115 +EXPORT_C TStreamId CDbStoreDatabase::ConstructL()
1.116 + {
1.117 + __ASSERT(iStore); // this must have been provided by now
1.118 + iVersion=TUint8(EDbStoreVersion2);
1.119 + InitPagePoolL();
1.120 + iPagePool->Create(Store());
1.121 + iTokenId=Store().ExtendL();
1.122 + ReplaceTokenL(0);
1.123 + iSchemaId=Store().ExtendL();
1.124 + Schema().Loaded();
1.125 + ReplaceSchemaL();
1.126 + return iSchemaId;
1.127 + }
1.128 +
1.129 +// SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
1.130 +// Open phase #2: Authenticate the client
1.131 +//
1.132 +EXPORT_C void CDbStoreDatabase::AuthenticateL()
1.133 + {
1.134 + if (!iPagePool)
1.135 + {
1.136 + // first client to open the database, so complete initialisation now
1.137 + InitPagePoolL();
1.138 + SchemaL();
1.139 + }
1.140 + }
1.141 +
1.142 +// SYMBIAN_REMOVE_TRIVIAL_ENCRYPTION version of the method.
1.143 +void CDbStoreDatabase::InitPagePoolL()
1.144 + {
1.145 + iPagePool = new(ELeave) RStorePagePool;
1.146 + }
1.147 +
1.148 +
1.149 +CDbSource* CDbStoreDatabase::OpenL(CStreamStore* aStore,TStreamId aStreamId)
1.150 + {
1.151 + CDbStoreDatabase* self=NewLC(aStore);
1.152 + self->RestoreL(aStreamId);
1.153 + CDbSource* src=self->SourceL();
1.154 + CleanupStack::Pop(); // self
1.155 + return src;
1.156 + }
1.157 +
1.158 +//
1.159 +// Phase 2 construction for opening a database
1.160 +// Client must still authenticate before it can be used
1.161 +//
1.162 +EXPORT_C void CDbStoreDatabase::RestoreL(TStreamId aStreamId)
1.163 + {
1.164 + __ASSERT(iStore); // this must have been provided by now
1.165 + iSchemaId=aStreamId;
1.166 +// read the databse header for encryption information
1.167 + RStoreReadStream strm;
1.168 + strm.OpenLC(Store(),aStreamId);
1.169 + ReadHeaderL(strm);
1.170 + CleanupStack::PopAndDestroy(); // strm
1.171 + }
1.172 +
1.173 +//
1.174 +// Load the root stream header (up to the security key)
1.175 +//
1.176 +void CDbStoreDatabase::ReadHeaderL(RReadStream& aStream)
1.177 + {
1.178 + TUid uid;
1.179 + aStream>>uid;
1.180 + if (uid!=KDbmsStoreDatabase)
1.181 + __LEAVE(KErrArgument);
1.182 + aStream>>iVersion;
1.183 + switch (iVersion)
1.184 + {
1.185 + case EDbStoreCompressed:
1.186 + aStream>>CompressionL();
1.187 + break;
1.188 + case EDbStoreVersion2:
1.189 + break;
1.190 + default:
1.191 + __LEAVE(KErrNotSupported);
1.192 + break;
1.193 + }
1.194 + }
1.195 +
1.196 +CDbStoreCompression& CDbStoreDatabase::CompressionL()
1.197 + {
1.198 + CDbStoreCompression* c=iCompression;
1.199 + if (!c)
1.200 + iFilter=iCompression=c=CDbStoreCompression::NewL();
1.201 + return *c;
1.202 + }
1.203 +
1.204 +EXPORT_C CDbStoreDatabase::~CDbStoreDatabase()
1.205 + {
1.206 + if (iPageCache)
1.207 + {
1.208 + iPagePool->Release();
1.209 + delete iPageCache;
1.210 + }
1.211 + delete iClusterCache;
1.212 + delete iPagePool;
1.213 + delete iCompression;
1.214 + if (!iSharedStore)
1.215 + delete iStore;
1.216 + }
1.217 +
1.218 +//
1.219 +// Validate the column set first
1.220 +//
1.221 +EXPORT_C CDbTableDef* CDbStoreDatabase::CreateTableL(const TDesC& aName,const CDbColSet& aColSet,const CDbKey* aPrimaryKey)
1.222 + {
1.223 + if (aPrimaryKey)
1.224 + __LEAVE(KErrNotSupported); // Store database does not support primary keys
1.225 + CDbStoreDef* def=CDbStoreDef::NewLC(aName,aColSet);
1.226 + def->SetTokenId(CDbStoreRecords::CreateL(ClusterCacheL()));
1.227 + CleanupStack::Pop();
1.228 + return def;
1.229 + }
1.230 +
1.231 +EXPORT_C CDbTableIndexDef* CDbStoreDatabase::CreateIndexL(const CDbTableDef& aTable,const TDesC& aName,const CDbKey& aKey)
1.232 + {
1.233 + CDbStoreIndexDef* def=CDbStoreIndexDef::NewLC(aName,aKey,aTable.Columns());
1.234 + def->SetTokenId(CDbStoreIndex::CreateL(*this,*def));
1.235 + CleanupStack::Pop(); // IndexDef
1.236 + return def;
1.237 + }
1.238 +
1.239 +//
1.240 +// Destroy the entire database...
1.241 +//
1.242 +EXPORT_C void CDbStoreDatabase::DestroyL()
1.243 + {
1.244 + iPagePool->Discard();
1.245 + iPagePool->ReclaimAllL(); // reclaim all page pool space
1.246 + iStore->DeleteL(iSchemaId);
1.247 + iStore->DeleteL(iTokenId);
1.248 + iStore->CommitL();
1.249 + }
1.250 +
1.251 +EXPORT_C CDbTable* CDbStoreDatabase::TableL(const CDbTableDef& aDef)
1.252 + {
1.253 + return new(ELeave) CDbStoreTable(*this,aDef);
1.254 + }
1.255 +
1.256 +//
1.257 +// load the schema for the database
1.258 +//
1.259 +EXPORT_C void CDbStoreDatabase::LoadSchemaL()
1.260 + {
1.261 + RDbStoreReadStream strm(*this);
1.262 + strm.OpenLC(Store(),iSchemaId);
1.263 + ReadHeaderL(strm);
1.264 + strm.FilterL(strm.EMixed,iSchemaId.Value());
1.265 + strm>>iTokenId;
1.266 + RDbTableSchema& schema=Schema();
1.267 + TCardinality tables;
1.268 + strm>>tables;
1.269 + for (TInt ii=tables;ii>0;--ii)
1.270 + schema.Add(CDbStoreDef::NewL(strm));
1.271 + CleanupStack::PopAndDestroy();
1.272 + strm.OpenLC(Store(),iTokenId);
1.273 + strm>>iFlags>>iPoolToken;
1.274 + iPagePool->Open(Store(),iPoolToken);
1.275 + CleanupStack::PopAndDestroy();
1.276 + }
1.277 +
1.278 +//
1.279 +// Re-write the schema stream
1.280 +//
1.281 +void CDbStoreDatabase::ReplaceSchemaL()
1.282 + {
1.283 + RDbStoreWriteStream out(*this);
1.284 + out.ReplaceLC(Store(),iSchemaId);
1.285 + out<<KDbmsStoreDatabase<<iVersion;
1.286 + switch (iVersion)
1.287 + {
1.288 + case EDbStoreCompressed:
1.289 + __ASSERT(iCompression);
1.290 + out<<*iCompression;
1.291 + break;
1.292 + case EDbStoreVersion2:
1.293 + break;
1.294 + default:
1.295 + __ASSERT(0);
1.296 + }
1.297 + out.FilterL(out.EMixed,iSchemaId.Value());
1.298 + out<<iTokenId;
1.299 + TSglQueIterC<CDbStoreDef> iter(Schema());
1.300 + TInt count=0;
1.301 + while (iter++)
1.302 + ++count;
1.303 + out<<TCardinality(count);
1.304 + iter.SetToFirst();
1.305 + for (const CDbStoreDef* def;(def=iter++)!=0;)
1.306 + out<<*def;
1.307 + out.CommitL();
1.308 + CleanupStack::PopAndDestroy();
1.309 + }
1.310 +
1.311 +//
1.312 +// Re-write the token stream, removing the mark
1.313 +//
1.314 +void CDbStoreDatabase::ReplaceTokenL(TUint aFlags)
1.315 + {
1.316 + RStoreWriteStream out;
1.317 + out.ReplaceLC(Store(),iTokenId);
1.318 + out<<TUint8(aFlags&EDamaged)<<iPagePool->Token();
1.319 + out.CommitL();
1.320 + CleanupStack::PopAndDestroy();
1.321 + }
1.322 +
1.323 +//
1.324 +// Return some database property
1.325 +//
1.326 +EXPORT_C TInt CDbStoreDatabase::Property(CDbDatabase::TProperty aProperty)
1.327 + {
1.328 + switch (aProperty)
1.329 + {
1.330 + case CDbDatabase::EIsDamaged:
1.331 + return iFlags&EDamaged ? 1 : 0;
1.332 + case CDbDatabase::ECompactable:
1.333 + return 1;
1.334 + default:
1.335 + return CDbTableDatabase::Property(aProperty);
1.336 + }
1.337 + }
1.338 +
1.339 +//
1.340 +// mark the database as dirty
1.341 +//
1.342 +void CDbStoreDatabase::MarkL()
1.343 + {
1.344 + if (!(iFlags&EModified))
1.345 + {
1.346 + RStoreWriteStream out;
1.347 + out.OpenLC(Store(),iTokenId);
1.348 + out.WriteUint8L(EDamaged); // mark as dirty
1.349 + iPoolToken.Touch();
1.350 + out<<iPoolToken;
1.351 + out.CommitL();
1.352 + CleanupStack::PopAndDestroy();
1.353 + iFlags|=EModified;
1.354 + }
1.355 + }
1.356 +
1.357 +//
1.358 +// Reset all cache buffers
1.359 +//
1.360 +EXPORT_C void CDbStoreDatabase::Idle()
1.361 + {
1.362 + if (iPageCache)
1.363 + {
1.364 + iPagePool->Purge();
1.365 + delete iPageCache;
1.366 + iPageCache=NULL;
1.367 + }
1.368 + if (iClusterCache)
1.369 + {
1.370 + delete iClusterCache;
1.371 + iClusterCache=NULL;
1.372 + }
1.373 + }
1.374 +
1.375 +//
1.376 +// Commit the store, and when all is well, clear the token
1.377 +//
1.378 +void CDbStoreDatabase::SynchStoreL(TDbLockType aLock)
1.379 + {
1.380 + if (iPageCache)
1.381 + iPagePool->FlushL();
1.382 + TUint newflags=iFlags&~EModified;
1.383 + if (aLock==EDbRecoveryLock)
1.384 + newflags&=~EDamaged;
1.385 + if (aLock==EDbRecoveryLock || iFlags&EModified)
1.386 + ReplaceTokenL(newflags);
1.387 + if (aLock>=EDbWriteLock || iSharedStore)
1.388 + {
1.389 + iStore->CommitL();
1.390 + iFlags=TUint8(newflags);
1.391 + iPoolToken=iPagePool->Token();
1.392 + }
1.393 + }
1.394 +
1.395 +//
1.396 +// An index has been successfully recovered, commit it
1.397 +//
1.398 +void CDbStoreDatabase::IndexRecoveredL()
1.399 + {
1.400 + SynchStoreL(EDbSchemaLock);
1.401 + }
1.402 +
1.403 +//
1.404 +// Ensure all data is in the store
1.405 +//
1.406 +EXPORT_C void CDbStoreDatabase::SynchL(TDbLockType aLock)
1.407 + {
1.408 + if (aLock==EDbSchemaLock)
1.409 + ReplaceSchemaL();
1.410 + if (iClusterCache)
1.411 + iClusterCache->FlushL();
1.412 + SynchStoreL(aLock);
1.413 + }
1.414 +
1.415 +//
1.416 +// Unwind the store, throw out changes, etc
1.417 +//
1.418 +EXPORT_C void CDbStoreDatabase::Revert(TDbLockType aLock)
1.419 + {
1.420 + if (aLock>=EDbWriteLock)
1.421 + {
1.422 + if (iClusterCache)
1.423 + iClusterCache->Discard();
1.424 + if (iPageCache)
1.425 + iPagePool->Purge();
1.426 + if (iFlags&EModified)
1.427 + iFlags|=EDamaged;
1.428 + iPagePool->Open(Store(),iPoolToken); // reset the page pool
1.429 + }
1.430 + else if (!iSharedStore) // don't touch the store if not shared
1.431 + return;
1.432 + iStore->Revert();
1.433 + }
1.434 +
1.435 +//
1.436 +// Ensure we have a cluster cache and return it
1.437 +//
1.438 +CClusterCache& CDbStoreDatabase::ClusterCacheL()
1.439 + {
1.440 + CClusterCache* cache=iClusterCache;
1.441 + if (!cache)
1.442 + iClusterCache=cache=CClusterCache::NewL(*this);
1.443 + return *cache;
1.444 + }
1.445 +
1.446 +//
1.447 +// Ensure we have a page cache and return the pool
1.448 +//
1.449 +MPagePool& CDbStoreDatabase::PagePoolL()
1.450 + {
1.451 + if (!iPageCache)
1.452 + {
1.453 + iPageCache=CPageCache::NewL(EPageCachePages);
1.454 + iPagePool->Set(*iPageCache);
1.455 + }
1.456 + return *iPagePool;
1.457 + }
1.458 +
1.459 +//
1.460 +// Create an incremental object that compacts the store
1.461 +//
1.462 +EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::UtilityL(CDbDatabase::TUtility aType,TInt& aStep)
1.463 + {
1.464 + switch (aType)
1.465 + {
1.466 + case CDbDatabase::EStats:
1.467 + case CDbDatabase::ECompact:
1.468 + return CCompactor::NewL(aType,Store(),iReclaim,aStep);
1.469 + case CDbDatabase::ERecover:
1.470 + return RecoverL(aStep);
1.471 + default:
1.472 + return CDbTableDatabase::UtilityL(aType,aStep);
1.473 + }
1.474 + }
1.475 +
1.476 +//
1.477 +// Create an incremental object to destroy a table
1.478 +//
1.479 +EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::RecordDiscarderL(const CDbTableDef& aTable,TInt& aStep)
1.480 + {
1.481 + CDbStoreTable::CDiscarder* discarder=new(ELeave) CDbStoreTable::CDiscarder;
1.482 + CleanupStack::PushL(discarder);
1.483 + aStep=discarder->OpenL((CDbStoreTable*)TableL(aTable));
1.484 + CleanupStack::Pop();
1.485 + return discarder;
1.486 + }
1.487 +
1.488 +//
1.489 +// Create an incremental object to destroy an index
1.490 +//
1.491 +EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::IndexDiscarderL(const CDbTableDef& aTable,const CDbTableIndexDef& anIndex,TInt& aStep)
1.492 + {
1.493 + CDbStoreIndex::CDiscarder* discarder=new(ELeave) CDbStoreIndex::CDiscarder;
1.494 + CleanupStack::PushL(discarder);
1.495 + CDbStoreIndex* index=CDbStoreIndex::NewL(*this,(const CDbStoreIndexDef&)anIndex,aTable);
1.496 + aStep=discarder->Open(index);
1.497 + index->OpenL();
1.498 + CleanupStack::Pop();
1.499 + return discarder;
1.500 + }
1.501 +
1.502 +//
1.503 +// Provide a stepper to alter the table data
1.504 +// if no data to alter, return 0
1.505 +//
1.506 +EXPORT_C CDbTableDatabase::CStepper* CDbStoreDatabase::TableAlterL(CDbTableDef& aTable,const HDbColumnSet& aNewSet,TInt& aStep)
1.507 + {
1.508 + CDbStoreDef& def=STATIC_CAST(CDbStoreDef&,aTable);
1.509 +//
1.510 + aStep=CDbStoreRecords::CardinalityL(Store(),def);
1.511 + if (!aStep)
1.512 + return NULL; // no data to modify
1.513 +
1.514 +// check that all added columns are nullable
1.515 + HDbColumnSet::TIteratorC col=aNewSet.Begin();
1.516 + HDbColumnSet::TIteratorC end=aNewSet.End();
1.517 + do
1.518 + {
1.519 + if (col->iFlags&TDbColumnDef::EAdded && col->iAttributes&TDbCol::ENotNull)
1.520 + __LEAVE(KErrArgument); // added column is not nullable
1.521 + } while (++col<end);
1.522 +//
1.523 +// check to see if anything is being dropped or changed type
1.524 + col=aTable.Columns().Begin();
1.525 + end=aTable.Columns().End();
1.526 + while (!(col->iFlags&(TDbColumnDef::EDropped|TDbColumnDef::EChangedType|TDbColumnDef::EChangedLen)))
1.527 + {
1.528 + if (++col==end)
1.529 + { // no changes which affect layout, so no work required
1.530 + aStep=0;
1.531 + return NULL;
1.532 + }
1.533 + }
1.534 +// work required
1.535 + CDbStoreTable::CAlter* alter=new(ELeave) CDbStoreTable::CAlter;
1.536 + CleanupStack::PushL(alter);
1.537 + alter->OpenL((CDbStoreTable*)TableL(def),aNewSet);
1.538 + CleanupStack::Pop();
1.539 + return alter;
1.540 + }
1.541 +
1.542 +EXPORT_C void CDbStoreDatabase::Reserved_1()
1.543 + {
1.544 + }
1.545 +
1.546 +EXPORT_C void CDbStoreDatabase::Reserved_2()
1.547 + {
1.548 + }
1.549 +