CentRepExample
: Using central repository for
persistent storage
This example application demonstrates the usage of Central repository API
for persistent storage. It is located in the folder
examples\SysLibs\CentRepExample
.
The overview contains the following sections:
Several Symbian OS components have state and settings information that need to be persistent. There is also a global state that needs to persist, for example, default filenames, locale settings, user preferences.
The CentRep example application first registers a group of settings
with the central repository server. It uses E80000AD.txt
, a UTF-16
format text file to initialise the repository. This text file contains access
control structure and the initial content of the repository. It is recommended
to convert the initialisation text file into a binary file using the central
repository converter tool to speed up the execution.
The application creates a CRepository
object using
the CRepository::NewLC()
method to access a repository
using its UID. It resets the whole repository using
CRepository::Reset()
method with the contents in the
initialisation file.
Each setting stored in the repository will have a unique key to
identify the setting. This unique key is used to read and change the setting by
calling the CRepository::Get()
and
CRepository::Set()
methods respectively. The application
moves these keys to a different location using
CRepository::Move()
method and deletes them from their
original location.
The application also creates another CRepository
object to
demonstrate that, at any given point a repository cannot be opened with
READ/WRITE access by more than one client. In such situations, it
is recommended to start a transaction before a write operation using
CRepository::StartTransaction()
method. A transaction
guarantees the consistency and persistence of all values read and written
during the transaction.
Finally, the application requests the central repository server to notify any changes to the original settings.
The Symbian OS build process describes how to build an application.
The CentRepExample
builds an executable called
CentRepExample.exe
in the standard location
(\epoc32\release\winscw\<build_variant> for
CodeWarrior). After launching the executable, depending on the emulator you are
using, you may need to task away from the app launcher/shell screen to view the
console. Alternatively, adding the string text shell to the emulator
configuration file epoc.ini
causes the emulator to start in text
mode.
// BLD.INF
//
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
PRJ_EXPORTS
E80000AD.txt \epoc32\RELEASE\WINSCW\UDEB\Z\private\10202be9\E80000AD.txt
PRJ_MMPFILES
centrepexample.mmp
// centrepexample.mmp
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
TARGET centrepexample.exe
TARGETTYPE exe
UID 0xE80000AD
CAPABILITY WriteUserData CommDD WriteDeviceData ReadDeviceData ReadUserData NetworkServices
SOURCEPATH .
SOURCE CENTREPEXAMPLE.CPP
SOURCE asyncwaiter.cpp
USERINCLUDE .
SYSTEMINCLUDE \Epoc32\include
LIBRARY euser.lib
LIBRARY centralrepository.lib
// CCentRepExample .h
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file
Contains the CCentRepExample class.
*/
#ifndef __CENTREPEXAMPLE_H__
#define __CENTREPEXAMPLE_H__
// Symbian OS includes
#include <centralrepository.h>
/**
CCentRepExample is a class that makes use of the APIs in CRepository class
CRepository is the class that provides access to repository.
The class demonstrates how to open the created repository,read its settings,
change them, read the meta data settings, perform read-write operations
in a transaction, find settings, restore default settings, request
change notification and delete settings.
*/
class CCentRepExample :public CBase
{
public:
static CCentRepExample* NewLC();
~CCentRepExample();
void ResetL();
void OpenRepositoryL();
void RdChgSetL();
void RdSettingsL();
void ChangeSettingsL();
void MoveSettingsL();
void ResetAndNotifyL();
void FindSettingsL();
void TransactionFuncL();
void DeleteL();
private:
CCentRepExample();
void ConstructL();
private:
/** Pointer to the console interface */
CConsoleBase* iConsole;
/** Pointer to the class that provides access to a repository. */
CRepository* iRepository;
};
#endif //__CENTREPEXAMPLE_H__
// centrepexample.cpp
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file
This example program demonstrates the use of the Central Repository.
Before you run the program, convert the example repository in the text file to a binary format
using the CentRepConv tool.
The code demonstrates how to open this repository, read its settings,
change them, perform read-write operations in a transaction,
find settings, restore default settings, request change notifications
and delete settings.
*/
#include "centrepexample.h"
#include <e32cons.h>
#include "asyncwaiter.h"
_LIT(KTitle, "Central repository example");
_LIT(KTextPressAKey, "\n\nPress any key to step through the example");
_LIT(KExit,"\nPress any key to exit the application ");
_LIT(KPressAKey,"\nPress any key to continue \n");
_LIT(KOpen,"\n\nOpening the repository and displaying some initial settings");
_LIT(KChangeSet,"\nChanging some settings in the repository");
_LIT(KReadSet,"\nReading the changed settings");
_LIT(KTransact,"\n\nPerforming read and write transactions");
_LIT(KDelete,"\n\nCreating integer and real number settings and deleting them");
_LIT(KMove,"\n\nMoving the key to target position");
_LIT(KReset,"\nResetting settings to default values, and getting notifications that the changes have occurred");
_LIT(KFind,"\n\nFinding settings for simple and structured data");
_LIT(KFindl,"for FindL");
_LIT(KNonExisting,"\n\nValue of new setting is %d");
_LIT(KInt,"\nValue of setting with key x01 is %d");
_LIT(KReal,"\nValue of setting with key x02 is %f");
_LIT(KInteg,"\nValue of setting with key x06 is %d \n");
_LIT(KIntBefore,"\nValue of setting with key x01 before reset is %d");
_LIT(KIntAfter,"\nValue of setting with key x01 after reset is %d");
_LIT(KIdsFound,"\nFound %d settings");
_LIT(KString1_UpdatedValue, "Another string");
static const TUid KUidRepository = { 0xE80000AD };
const TUint32 KNonExistentSetting = 0x10;
const TUint32 KInt1 = 0x01;
const TUint32 KInt3 = 0x06;
const TUint32 KReal1 = 0x02;
const TUint32 KString1 = 0x05;
const TInt KInt1_InitialValue = 1;
const TInt KInt1_UpdatedValue = 73;
const TReal KReal1_InitialValue = 14.91;
const TReal KReal1_UpdatedValue = 72.8;
const TUint32 KMoveTarget = 0x30;
/**
Allocates and constructs a CCentRepExample object and
leaves it on the cleanup stack.
Initialises all member data to their default values.
*/
CCentRepExample* CCentRepExample::NewLC()
{
CCentRepExample* rep = new(ELeave) CCentRepExample();
CleanupStack::PushL(rep);
rep->ConstructL();
return rep;
}
/**
Constructor
*/
CCentRepExample::CCentRepExample()
{
}
void CCentRepExample::ConstructL()
{
iConsole = Console::NewL(KTitle,TSize(KConsFullScreen,KConsFullScreen));
iConsole->Printf ( KTextPressAKey );
iConsole->Getch ();
}
/**
Destructor
*/
CCentRepExample::~CCentRepExample()
{
iConsole->Printf(KExit);
iConsole->Getch();
delete iConsole;
delete iRepository;
}
/**
Resets the whole repository to the state of the initialization file
originally used to set it up.
@leave KErrNotSupported, system-wide error codes.
*/
void CCentRepExample::ResetL()
{
TInt err;
CRepository* aRepository;
aRepository = CRepository::NewLC(KUidRepository);
err = aRepository->Reset();
CleanupStack::PopAndDestroy(aRepository);
}
/**
Creates a CRepository object to access the
repository with the specified UID and displays some of the initial settings.
@leave KErrNotFound, KErrAbort, KErrPermissionDenied,
KErrArgument, system-wide error codes.
*/
void CCentRepExample::OpenRepositoryL()
{
TInt err, i, k;
TReal j;
TBuf<25> tooShort;
iConsole->Printf(KOpen);
iRepository = CRepository::NewL(KUidRepository);
err = iRepository->Get(KInt1, i);
iConsole->Printf(KInt,i);
err = iRepository->Get(KReal1, j);
iConsole->Printf(KReal,j);
err = iRepository->Get(KInt3, k);
iConsole->Printf(KInteg,k);
err = iRepository->Get(KString1, tooShort);
iConsole->Printf(tooShort);
iConsole->Printf(KPressAKey);
iConsole->Getch();
}
/**
Changes the value of an existing setting or
creates a new setting with a value if the setting doesn't exist.
@leave KErrAbort, KErrPermissionDenied, KErrArgument, system-wide error codes.
*/
void CCentRepExample::ChangeSettingsL()
{
TInt err;
iConsole->Printf(KChangeSet);
err = iRepository->Set(KNonExistentSetting, 10);
err = iRepository->Set(KInt1, KInt1_UpdatedValue);
err = iRepository->Set(KReal1, KReal1_InitialValue);
err = iRepository->Set(KInt3, 16);
err = iRepository->Set(KString1, KString1_UpdatedValue);
}
/**
Reads the changed settings and prints them.
@leave KErrNotFound, KErrAbort, KErrPermissionDenied,
KErrArgument, system-wide error codes.
*/
void CCentRepExample::RdSettingsL()
{
TInt err, m, i, k;
TReal j;
TBuf<25> tooShort;
iConsole->Printf(KReadSet);
err = iRepository->Get(KNonExistentSetting, m);
iConsole->Printf(KNonExisting,m);
err = iRepository->Get(KInt1, i);
iConsole->Printf(KInt,i);
err = iRepository->Get(KReal1, j);
iConsole->Printf(KReal,j);
err = iRepository->Get(KInt3, k);
iConsole->Printf(KInteg,k);
err = iRepository->Get(KString1, tooShort);
iConsole->Printf(tooShort);
iConsole->Printf(KPressAKey);
iConsole->Getch();
}
/**
Sets KInt1 to a different value, resets it and gets
notification that this value has changed.
@leave KErrAlreadyExists error from IPC or server side resource allocation failure
*/
void CCentRepExample::ResetAndNotifyL()
{
TInt x, err;
// Ensure KInt1 is set to a different value to its initial value
// First change to setting should cause notification
iConsole->Printf(KReset);
err = iRepository->Set(KInt1, KInt1_InitialValue+10);
err = iRepository->Get(KInt1, x);
iConsole->Printf(KIntBefore, x);
CAsyncWaiter* waiter = CAsyncWaiter::NewL();
CleanupStack::PushL(waiter);
err = iRepository->NotifyRequest(KInt1, waiter->iStatus);
// Get a notification on a reset as well
err = iRepository->Reset(KInt1);
// Check we got a notification
waiter->StartAndWait();
User::LeaveIfError(waiter->Result());
// Check KInt1 now has the right value
err = iRepository->Get(KInt1, x);
iConsole->Printf(KIntAfter, x);
CleanupStack::PopAndDestroy(waiter);
}
/**
Finds all the settings for both simple and structured data.
Finds all the settings that exist and match the specification given by
a partialKey and a mask.
Matches occur whenever (key & mask) == (partialKey & mask).
@leave KErrAbort, KErrPermissionDenied, KErrArgument, system-wide error codes.
*/
void CCentRepExample::FindSettingsL()
{
TInt err;
RArray<TUint32> foundIds;
// Finds all the settings that exist and match the specification
//given by partialKey and mask.
iConsole->Printf(KFind);
err = iRepository->FindL(0/*partialKey*/, 0x02/*mask*/, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
foundIds.Reset();
err = iRepository->FindL(0x04, 0x06, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
iConsole->Printf(KFindl);
foundIds.Reset();
// Finds all the settings that contain a given integer and
//match the specification given by partialKey and mask.
err = iRepository->FindEqL(0x00/*partialKey*/, 0x01/*mask*/, KInt1_InitialValue /*integer value*/, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
foundIds.Reset();
// Finds all the settings that contain a given floating point value
//and match the specification given by partialKey and mask.
err = iRepository->FindEqL(0x00, 0x01,KReal1_InitialValue/*Real value*/, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
foundIds.Reset();
// Finds all the settings that contain a given string value
//and match the specification given by partialKey and mask.
err = iRepository->FindEqL(0x05, 0xFF, KString1_UpdatedValue/*string*/, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
foundIds.Reset();
// Finds all the settings that match the specification given
// by partialKey and mask, but are either not integer values or
//do not have the given value.
err= iRepository->FindNeqL(0x02/*partial key*/, 0xFF/*mask*/, KInt1_UpdatedValue, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
foundIds.Reset();
// Finds all the settings that match the specification given by
//partialKey and mask, but are either not floating point values
//or do not have the given value.
err = iRepository->FindNeqL(0x01, 0xFF, KReal1_UpdatedValue, foundIds);
iConsole->Printf(KIdsFound,foundIds.Count());
foundIds.Reset();
}
/**
Perform read and write operations using transactions.
@leave KErrLocked, panic.
*/
void CCentRepExample::TransactionFuncL()
{
TUint32 keyId;
TInt intVal, err;
CRepository* repository1;
User::LeaveIfNull(repository1 = CRepository::NewLC(KUidRepository));
iConsole->Printf(KTransact);
// Begin read write transaction
err = iRepository->StartTransaction(CRepository::EReadWriteTransaction);
const TUint32 KNewInt = 0x16;
const TInt KIntValue = 1201;
intVal = KIntValue +33;
// perform some write operations
err = iRepository->Create(KNewInt, KIntValue);
err = iRepository->Set(KNewInt,intVal);
err = iRepository->CommitTransaction(keyId);
err = iRepository->Get(KNewInt, intVal);
if (err != KErrNone)
{
iRepository->FailTransaction();
}
err = iRepository->Delete(KNewInt);
// Begin transaction for repository1
err = repository1->StartTransaction(CRepository::EReadTransaction);
CRepository* repository2;
User::LeaveIfNull(repository2 = CRepository::NewLC(KUidRepository));
// Should be able to start another read transaction (Multiple read transactions)
err = repository2->StartTransaction(CRepository::EReadTransaction);
// Perform some gets using the open transactions and repositories
// Read operation
err = repository1->Get(KInt1, intVal);
// Ensure transaction cancelled if following code Leaves:
repository1->CleanupCancelTransactionPushL();
CleanupStack::Pop();
User::LeaveIfError(repository1->CommitTransaction(keyId));
err = repository2->Get(KInt1, intVal);
User::LeaveIfError(repository2->CommitTransaction(keyId));
if (err != KErrNone)
{
iRepository->FailTransaction();
}
CleanupStack::PopAndDestroy(2,repository1);
}
/**
Moves a key from one location to another.
@leave KErrAbort, KErrPermissionDenied, KErrArgument, system-wide error codes.
*/
void CCentRepExample::MoveSettingsL()
{
TInt err;
TUint32 keyInfo;
err = iRepository->StartTransaction(CRepository::EReadWriteTransaction);
iRepository->CleanupCancelTransactionPushL();
iConsole->Printf(KMove);
iConsole->Printf(KPressAKey);
iConsole->Getch();
// Move the key to the target position
err = User::LeaveIfError(iRepository->Move(KInt3, KMoveTarget, 0xFFFFFFFF,
keyInfo));
CleanupStack::Pop(); // transaction
err = iRepository->CommitTransaction(keyInfo);
}
/**
Deletes 2 settings KInt1_InitialValue and //KReal1_InitialValue
@leave KErrAbort, KErrPermissionDenied, KErrArgument, system-wide error codes.
*/
void CCentRepExample::DeleteL()
{
TInt x, err;
TReal y;
iConsole->Printf(KDelete);
err = iRepository->Get(KInt1_InitialValue, x);
err = iRepository->Get(KReal1, y);
err = iRepository->Delete(KInt1_InitialValue);
err = iRepository->Delete(KMoveTarget);
err = iRepository->Delete(KReal1);
}
LOCAL_C void MainL()
{
// Create an Active Scheduler to handle asychronous calls
CActiveScheduler* scheduler = new (ELeave) CActiveScheduler;
// If Active Scheduler has been created, install it .
// As it is an asychronous call we need to install it explicitly.
CActiveScheduler::Install( scheduler );
CCentRepExample * app = CCentRepExample ::NewLC();
// Reset the repository
app->ResetL();
app->OpenRepositoryL();
// Change the existing settings
app->ChangeSettingsL();
// Read the changed settings
app->RdSettingsL();
// Move settings
app->MoveSettingsL();
// Reset settings to default values and get notification
app->ResetAndNotifyL();
// Find the settings using FindL, FindEqL and FindNeqL
app->FindSettingsL();
// Perform multiple operations in a transaction
app->TransactionFuncL();
// Delete settings
app->DeleteL();
CleanupStack::PopAndDestroy(app);
delete scheduler;
}
GLDEF_C TInt E32Main()
{
__UHEAP_MARK;
CTrapCleanup* cleanup = CTrapCleanup::New();
if(cleanup == NULL)
{
return KErrNoMemory;
}
TRAPD(err, MainL());
if(err != KErrNone)
{
User::Panic(_L("Failed to complete"),err);
}
delete cleanup;
__UHEAP_MARKEND;
return KErrNone;
}
// asyncwaiter.h
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file
Contains the CAsyncWaiter class.
*/
#ifndef __ASYNCWAITER_H_
#define __ASYNCWAITER_H_
#include <e32base.h>
/**
CAsyncWaiter is a class that publicly inherits the class CActive.
CActive is core class of the active object abstraction.
It encapsulates both issuing a request to an asynchronous service provider
and handling the completed requests.
*/
class CAsyncWaiter : public CActive
{
public:
static CAsyncWaiter* NewL();
~CAsyncWaiter();
void StartAndWait();
TInt Result() const;
private:
CAsyncWaiter();
// CActive implementation
virtual void RunL();
virtual void DoCancel();
private:
TInt iError;
};
#endif // __ASYNCWAITER_H_
// asyncwaiter.cpp
//
// Copyright (c) Symbian Software Ltd 2006. All rights reserved.
//
/**
@file
This encapsulates both issuing a request to an asynchronous service provider
and handling the completed requests.
*/
#include "asyncwaiter.h"
/**
Creates an object of CAsyncWaiter
*/
CAsyncWaiter* CAsyncWaiter::NewL()
{
CAsyncWaiter* self = new(ELeave) CAsyncWaiter();
return self;
}
/**
Adds the active object to the scheduler
*/
CAsyncWaiter::CAsyncWaiter() : CActive(EPriorityStandard)
{
CActiveScheduler::Add(this);
}
CAsyncWaiter::~CAsyncWaiter()
{
Cancel();
}
/**
Indicates that the active object has issued a request
and that it is now outstanding .
*/
void CAsyncWaiter::StartAndWait()
{
SetActive();
CActiveScheduler::Start();
}
TInt CAsyncWaiter::Result() const
{
return iError;
}
/**
Handles an active object’s request completion event.
It sets to run the desired task.
*/
void CAsyncWaiter::RunL()
{
iError = iStatus.Int();
CActiveScheduler::Stop();
}
/**
Implements cancellation of an outstanding request.
This function is called as part of the active object's Cancel().
*/
void CAsyncWaiter::DoCancel()
{
iError = KErrCancel;
CActiveScheduler::Stop();
}
# E80000AD.txt
# Central repository
#
cenrep
version 1
[defaultMeta]
0
0x1 0xF 0
0x10 0x1F 1
0x20 0x2F 2
0x1000 mask = 0x04 0x00000040
[platsec]
#capabilities defined per range of indexes
0x01 0x50 cap_rd=AlwaysPass cap_wr=AlwaysPass
[main]
1 int 33 0 cap_rd=CommDD cap_wr=WriteDeviceData
2 real 2.732 0xa cap_rd=AlwaysPass cap_wr=AlwaysPass
5 string "This is a string" 2
6 int 12 0xf
8 real 1.5 1
11 string string 0x305
0x13 real 1.5 12
0x101 int 100 0