Symbian
Symbian OS Library

SYMBIAN OS V9.3

[Index] [Spacer] [Previous] [Next]



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:


Description

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.

[Top]


Class summary

[Top]


Build

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.

[Top]


Example code


bld.inf

// 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

// 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

// 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

// 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

//  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

//  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

# E80000AD.txt
# Central repository
#

cenrep
version 1
[defaultMeta]

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