28
Using Symbian OS DatasharingandpersistEnce

Data Sharing and Persistence With Symbian C++

  • Upload
    symbian

  • View
    136

  • Download
    1

Embed Size (px)

DESCRIPTION

This booklet about Data Sharing and Persistence is part of the "Using Symbian OS series", and describes the various mechanisms for storing information and sharing it between threads and processes. The article was formerly hosted on Symbian Developer Network. The evolving version of the article is here: http://developer.symbian.org/wiki/index.php/Data_Sharing_and_Persistence_with_Symbian_C%2B%2B

Citation preview

Page 1: Data Sharing and Persistence With Symbian C++

Using Symbian OS

DatasharingandpersistEnce

Page 2: Data Sharing and Persistence With Symbian C++
Page 3: Data Sharing and Persistence With Symbian C++

Reviewed by:Henry Boothroyd BrooksPhilip CheungRichard ColesHusien HongIvan LitovskiRichard MaynardMark ShackmanJo Stichbury

Data Sharing and Persistencepart of the Using Symbian OS series

1st edition, 01/09

Published by:Symbian Software Limited2-6 Boundary RowSouthwarkLondon SE1 8HPUKwww.symbian.com

Trademarks, copyright, disclaimer‘Symbian’, ‘Symbian OS’ and other associated Symbian marks are all trademarks of SymbianSoftware Ltd. Symbian acknowledges the trademark rights of all third parties referred to in thismaterial. Copyright © Symbian Software Ltd 2009. All rights reserved. No part of this materialmay be reproduced without the express written permission of Symbian Software Ltd. SymbianSoftware Ltd makes no warranty or guarantee about the suitability or the accuracy of theinformation contained in this document. The information contained in this document is forgeneral information purposes only and should not be used or relied upon for any otherpurpose whatsoever.

Compiled by:Anna Fisher

Managing Editor:Ashlee Godwin

Symbian Developer Networkdeveloper.symbian.com

Page 4: Data Sharing and Persistence With Symbian C++

Contents

Introduction .................................................................................................................................1

Symbian SQL ...............................................................................................................................1

Structured Query Language (SQL) ............................................................................................2

Symbian SQL API ......................................................................................................................3

Database access types .............................................................................................................6

Client-server issues...................................................................................................................6

Backing up databases ..............................................................................................................6

POSIX support ..........................................................................................................................7

Publish and Subscribe ................................................................................................................7

Properties .................................................................................................................................8

Publish and Subscribe API........................................................................................................8

Message queues .........................................................................................................................9

Basic message queue operations.............................................................................................9

Message queue API.................................................................................................................10

The Central Repository...............................................................................................................11

Key masks ...............................................................................................................................14

Central Repository API ............................................................................................................15

Backing up your repository.....................................................................................................16

The CentRepConv conversion tool ..........................................................................................17

Memory chunks .........................................................................................................................17

Conclusion .................................................................................................................................18

Page 5: Data Sharing and Persistence With Symbian C++

IntroductionThis booklet introduces four important mechanisms provided by Symbian OS for sharing datasecurely across threads and processes:

• Symbian SQL • Publish and Subscribe• Message queues• Central Repository.

Two of these mechanisms – Symbian SQL and the Central Repository – provide mechanisms forpersisting data. The other two – Publish and Subscribe and message queues – providemechanisms for transient communications (that is, the data that does not persist after thephone reboots).

This booklet ends with a brief mention of using shared memory regions (which are known aschunks). However, their use is beyond the scope of this booklet and is not covered in detail.We do not cover the Symbian OS client-server architecture, which is another mechanism forsharing data on Symbian OS. Similarly, we do not cover persisting data to files. For anintroduction to these topics, refer to the Symbian Press book, Developing Software forSymbian OS, Second Edition by Steve Babin, at developer.symbian.com/main/documentation/books/books_files/dasos/index.jsp.

Symbian SQL Symbian OS includes an SQL database service to applications and other Symbian OS softwarecomponents. As Figure 1 shows, it is implemented using the Symbian OS client-server modeland is based on the SQLite database engine. SQLite is a widely deployed open sourcedatabase engine. You can find out more about SQLite at www.sqlite.org.

Figure 1: Symbian SQL

1

Page 6: Data Sharing and Persistence With Symbian C++

Structured Query Language (SQL)SQL is a standard language for querying and modifying data and managing databases.

Here is an example of the data definition part of the language (DDL) that shows using theCREATE keyword to create a database table:

CREATE TABLE booking (booking_no INTEGER PRIMARY KEY, event_no INTEGER NOT NULL, student_name TEXT NOT NULL

);

Notice that we are using the PRIMARY KEY keyword which causes a unique index to becreated automatically.

We can then use the data manipulation language (DML) keywords INSERT INTO to add arecord to the table:

INSERT INTO booking (event_no, student_name)

VALUES (1003, "Bridget Jones");

Other common DML keywords are UPDATE to modify data and DELETE FROM to deleterecords.

Finally, here is an example of a query, which is the most common type of SQL operation:

SELECT student_name, event_noFROM booking ORDER BY student_name;

This returns a record set containing a row for each record in the booking table, sorted indescending alphabetical order of student name.

Queries start with the SELECT keyword. You can use the WHERE clause to restrict the resultsto certain criteria and you can use ORDER BY to sort the results. The supported query syntaxis extensive and includes using JOIN to combine the results from two or more tables (unlikethe older Symbian OS DBMS database service, which does not support the JOIN keyword).

There is a full list of the SQL language supported by SQLite at www.sqlite.org/lang.html. With one or two minor exceptions, Symbian SQL supports the full range of SQL syntax that issupported by SQLite. Symbian SQL does not support the PRAGMA keyword, and ATTACH andDETACH are deprecated in Symbian SQL in favor of functions available in the API and will failif applied to a secure database.

Like many programming languages, you can often achieve the same results in more than oneway, but some ways are more efficient than others. Some of the details are specific to how theunderlying components have been implemented. For detailed information about the best wayto write SQL for Symbian OS, seedeveloper.symbian.com/main/documentation/sdl/symbian94/sdk/doc_source/guide/System-Libraries-subsystem-guide/SQL/SQlHowToMakeEfficientUseOf.guide.html.

2

Page 7: Data Sharing and Persistence With Symbian C++

Symbian SQL APISymbian SQL has two fundamental client-side classes: RSqlDatabase andRSqlStatement.

RSqlDatabaseRSqlDatabase is a handle to the SQL database. This provides functions for creating,opening, copying and deleting a database, etc. Here is an example of creating a non-securedatabase:

RSqlDatabase myDatabase;_LIT(KDBFileName, "C:\\public\\data\\MyDatabase.db");TInt err = myDatabase.Create(KDBFileName);

You can create a secure database by passing the security policies that you want to apply tothe database to the Create() method. We’ll look at the database access types in the‘Database access types’ section later in the booklet.

You can use the Open() method to open an existing database. For example:

TInt err = myDatabase.Open(KDBFileName);

And as you might expect, you use Close() to close the handle to the database to freeallocated resources.

RSqlDatabase also provides an Exec() function for executing a simple one-shot SQLstatement. Here we are executing a simple DML statement to update a record in the event table:

_LIT(KUpdateString, "UPDATE event SET available_spaces=8 WHERE event_no=1004");

TInt ret = myDatabase.Exec(KUpdateString);

You can use the same approach to insert a row into the table. However, in real code you oftenneed to insert multiple rows, using different values each time. One way to do this is to buildup a different SQL statement for each row. A more efficient alternative, however, is to use theRSqlStatement class, which enables you to prepare a single statement and substitutedifferent parameters for each row, as shown in the code sample on the next page.

RSqlStatementBut first let’s look at an example of using RSqlStatement to execute a SELECT statement.You must use RSqlStatement to execute SELECT statements because RSqlDatabasedoes not provide a mechanism for accessing the results of a query.

Here is an example:

_LIT(KSelectString, "SELECT title, cost FROM course");

RSqlStatement myStatement; // 1 CleanupClosePushL(myStatement);

myStatement.PrepareL(myDatabase, KSelectString); // 2

TInt ret;

3

Page 8: Data Sharing and Persistence With Symbian C++

while ((ret = myStatement.Next()) == KSqlAtRow) // 3 {TPtrC title = myStatement.ColumnTextL(0); // 4 TInt cost = myStatement.ColumnInt(1);

// ... Use the values

}

if (ret != KSqlAtEnd){User::LeaveIfError(ret);}

CleanupStack::PopAndDestroy(&myStatement); // 5

This follows a standard pattern:1. Create the RSqlStatement object and push it onto the cleanup stack.2. Prepare the statement.3. Retrieve a record from the result set. 4. Read the results from specified columns – the argument denotes the column number in the

returned record set. Notice that we use different functions, depending on the data type. (Ifnecessary, you can use the ColumnType() function to find out the data type.)

5. Pop and destroy the RSqlStatement object from the cleanup stack.

Notice that in this example we are potentially retrieving multiple rows from the table, so weread the results and retrieve the next record in a loop. We execute the loop while the returncode is KSqlAtRow. This means that we drop out of the loop if an error occurs when weretrieve a row. If no errors occur, the loop ends when we get to the end of the rows(KSqlAtEnd). We must also check the return value after the end of the loop in order tohandle any errors.

As mentioned earlier, RSqlStatement is also useful when you need to execute multiple DMLstatements (such as INSERT and UPDATE), because you can prepare the statement once andthen substitute parameters. For example, you can use this technique to add multiple rows to adatabase table, like this:

RSqlStatement myStatement; // 1CleanupClosePushL(myStatement);

_LIT(KInsertString, "INSERT INTO booking (event_no, student_name) \VALUES (:event_no, :student_name)");

myStatement.PrepareL(myDatabase, KInsertString);

_LIT(KEvent, ":event_no"); _LIT(KName, ":student_name");

TInt eventParam = myStatement.ParameterIndex(KEvent); // 2TInt nameParam = myStatement.ParameterIndex(KName);

for (TInt i = 0; i < numRecords; i++) // 3{

4

Page 9: Data Sharing and Persistence With Symbian C++

User::LeaveIfError(myStatement.BindInt(eventParam, events[i]));User::LeaveIfError(myStatement.BindText(nameParam,(*names)[i]));User::LeaveIfError(myStatement.Exec());myStatement.Reset();}

CleanupStack::PopAndDestroy(&myStatement); // 4

These are the steps:1. As in the previous example, we start by creating the RSqlStatement, pushing it to the

cleanup stack and calling PrepareL() to prepare the statement. Notice that we haveused the :column_name syntax in the SQL statement to represent a parameter, to whichwe can bind a value.

2. Then we retrieve the indexes of the two parameters and store them in local variables. Thisis an alternative to simply specifying their numeric indexes.

3. For each record that we want to add to the table, we first bind values to the twoparameters (notice that the function we use depends on the type of data we are binding).Then we call Exec() to execute the statement followed by Reset() to reset theprepared statement to its original state so that it is now ready to bind new values in thenext iteration of the loop.

4. Finally, we pop and destroy the RSqlStatement object from the cleanup stack.

When you need to do more than one INSERT, UPDATE or DELETE operation, it is best toexecute them within an explicit transaction. You do this by executing the BEGIN statementprior to the first change and executing COMMIT after all of the changes have finished. This notonly avoids inconsistencies in the data but also speeds performance, because only one time-consuming COMMIT operation occurs.

For example, we could add the following code before the first line of the previous example toexecute BEGIN:

_LIT(KBeginTransaction, "BEGIN"); User::LeaveIfError(myDatabase.Exec(KBeginTransaction)); CleanupStack::PushL(TCleanupItem(DoRollback, &myDatabase));

Notice that we have pushed a TCleanupItem that points to a rollback function onto thecleanup stack. This means that we can revert the changes if a leave occurs mid-transaction.Here is an example of the rollback function:

void DoRollback(TAny* aDbHandle){_LIT(KRollbackTransaction, "ROLLBACK");if (aDbHandle)

{RSqlDatabase* myDb = static_cast<RSqlDatabase*>(aDbHandle);myDb->Exec(KRollbackTransaction);}

}

Then we would add the following to execute COMMIT. We need to add this after the loop thatexecutes the INSERT statements:

5

Page 10: Data Sharing and Persistence With Symbian C++

_LIT(KCommitTransaction, "COMMIT");User::LeaveIfError(myDatabase.Exec(KCommitTransaction)); CleanupStack::Pop();

Database access types There are three database access types: public shareable, private and secure shareable. Theaccess type is defined when you create the database.

• To create a public shareable database, do not provide a security policy, then create thedatabase in a public folder, as shown in the example in the ‘RSqlDatabase’ section.

• To create a private database, use the same syntax but with the location set to theapplication’s private data cage.

• To create a secure shareable database, you need to provide one or more security policiesin a container. The database is then automatically created in the SQL server’s private datacage. For an example of creating a secure shareable database, seedeveloper.symbian.com/main/documentation/sdl/symbian94/sdk/doc_source/guide/System-Libraries-subsystem-guide/SQL/UsingSymbianSQLFramework.html.

Client-server issuesBecause Symbian SQL is implemented using the Symbian OS client-server model, two or moreapplications or processes can share a secure database without the need to wrap it within itsown server. However, sometimes you might need to consider implementing an intermediateserver, for example, if you want to provide notifications when the database is updated(currently, Symbian SQL does not provide notifications).

Backing up databasesSymbian OS includes software to back up data to, and restore data from, a connected PC. Ifyou want your application’s data and files to be backed up and restored, you need to createan XML registration file (called backup_registration.xml) in the application’s privatedata cage. This should specify the names of the files and/or directories to be backed up andrestored, including your private and public databases. For a public or private database, yousimply need to include the name or directory of the database in the backup registration file.

In the example below, the passive_backup element specifies that the entire private datacage directory should be backed up.

<?xml version="1.0" standalone="yes" ?> <backup_registration version="1.0">

<passive_backup><include_directory name = "\" />

</passive_backup><proxy_data_manager SID="0x10281e17" /><restore requires_reboot="no" />

</backup_registration>

For a secure shareable database, use the SID attribute of the proxy_data_managerelement in the backup registration file and set it to the Symbian SQL server’s secure ID (SID)of 0x10281e17, as highlighted in the example above.

6

Page 11: Data Sharing and Persistence With Symbian C++

POSIX supportSymbian OS v9.5 will provide the native SQLite C API as part of its P.I.P.S. offering. P.I.P.S. is arecursive abbreviation for ‘P.I.P.S. Is POSIX on Symbian OS’ and provides an API layer, abovethe native Symbian C++ APIs, that is more closely aligned with industry standard APIs. Thismakes Symbian OS more accessible to developers who program using the Standard Clanguage. For more information about P.I.P.S., please seedeveloper.symbian.com/main/documentation/books/books_files/pdf/P.I.P.S..pdf.

Publish and SubscribePublish and Subscribe provides a mechanism for defining and publishing global properties, whichcan be integer values, descriptors or byte arrays. This mechanism is useful for publishingproperties that are not suited to the one-to-one communication offered by client-servercommunication.

Publish and Subscribe is suitable for transient settings only because the properties are notpreserved when the phone shuts down, although they persist beyond the lifetime of the definingprocess. Typical scenarios include multicasting the status of battery and communication links.

Figure 2: Publish and Subscribe

As Figure 2 illustrates, a publisher is a thread that defines and sets a property and asubscriber is a thread that reads a property’s value and subscribes to notifications of changes.The publisher and subscriber can be different threads within the same process or differentprocesses. Any program can act as a publisher or subscriber or both. Publishers andsubscribers do not need to know about each other or link to special client APIs.

Publish and Subscribe can be used to notify critical tasks that require real-time guarantees.When real-time guarantees are not required, Publish and Subscribe can be used to triggeractions that are based on the state of the property even when the client has missed aprevious state.

For properties that are updated frequently, it is recommended that you do not perform asubstantial amount of processing on each update notification because this can negativelyaffect performance.

7

Page 12: Data Sharing and Persistence With Symbian C++

PropertiesA Publish and Subscribe property has an identity and a type:

• The identity consists of a 64-bit integer made up of a category and a key. The category isidentified by a UID, which is normally the secure ID (SID) of the process that defines theproperty. An error is generated if any other process attempts to delete the property. Ineffect, this forms a data cage, preventing a process from defining, or ‘occupying,’ anotherprocess's property. The key is a 32-bit value that identifies the property within the category.

• The type defines the data type that can be stored in the property. It can be a single 32-bit value, a contiguous set of bytes, referred to as a byte array, or Unicode text. Bytearrays and text properties are both limited to 512 bytes; there are separate types forlarger arrays but these cannot be used in real-time code.

A property’s identity, type and value are the only things that are shared between thepublisher(s) and subscriber(s).

Publish and Subscribe API For a program to use the Publish and Subscribe service, it must declare an RPropertyobject. This provides methods as follows:

• Define() – create a property and define its type and identity, optionally specifyingsecurity policies

• Delete() – remove a property from the system• Set() – change the value of a property• Get() – retrieve the value of a property• Attach() – create a handle to a property• Subscribe() – register for notification of changes • Cancel() – unsubscribe to notification of changes.

The write operations are atomic, which means that they either succeed or do nothing. As aresult, when a thread reads a property, the data is guaranteed to be valid.

Setting and getting values is accomplished in bounded time (and are thus suitable for real-time code) under the following conditions:

• The value being published is either a 32-bit value, or a byte array that has beenpreallocated to a sufficient length at Define() time.

• The publishing thread already has an RProperty object that has been attached to thedesired category/property using Attach(), and the one-argument version ofSet()/Get() is used.

Note that the following are not accomplished in bounded time and are therefore not suitablefor real-time code:

• defining and deleting properties• any operations on the large byte array type.

For examples of their use and further documentation, please seedeveloper.symbian.com/main/documentation/sdl/symbian94/sdk/doc_source/guide/Base-subsystem-guide/e32/PublishAndSubscribe/UsingPublishSubscribe.guide.html.

Also see the Publish and Subscribe white paper on the Symbian Developer Network:developer.symbian.com/main/downloads/papers/publishandsubscribe/PublishAndSubscribe_v1.0.pdf

8

Page 13: Data Sharing and Persistence With Symbian C++

Message queuesSymbian OS message queues also allow the sharing of transient data, by providing one-way,one-to-one communication between two threads. Threads can send and receive messages froma message queue, be notified when a message enters the queue and be notified when spacebecomes available in the queue.

Message queues lend themselves to the passing of memory buffers from one thread to anotherin the same or different processes. This usage can be employed effectively for processing intensiveand/or multimedia applications.

Figure 3: Message queue

As Figure 3 illustrates, a message queue is a block of memory in the kernel. Each message is aslot in that memory and there are a fixed number of slots, determined at the time of creation.Messages are therefore of fixed size and the queue has a limited capacity and can potentially runout of space. This means that message queues are not real-time safe – it is not possible to writea message to a queue in bounded time because the queue may be full.

Message queues are transient: neither the messages nor the queues are persistent. When the lasthandle to the queue is closed, cleanup is performed and the messages and queue disappear.

Message queues can be created ‘locally’ to allow communication between threads in the sameprocess, or ‘globally’ to allow threads in different processes to communicate. A global messagequeue can be named and publicly visible to other threads or it can be anonymous, which meansthat it does not have a registered global name. Using a global name is not recommended becauseit is insecure. When using an anonymous message queue, you share its handle with a child processat creation time, or with any process via the client-server architecture. This prevents otherprocesses from accessing the queue, which makes it a more secure way of sharing messages.

Basic message queue operationsBasic message queue operations include:

• Creating and opening a message queue.• Sending a message – either using the blocking option, which waits for space if the queue

is full, or the non-blocking option, which does not wait if the queue is full, (that is, themessage is not sent).

• Receiving a message – this removes the message from the queue, hence it is unicast.There are blocking and non-blocking receive options, just like for sending.

• Requesting to be notified when space becomes available in the queue and/or when dataarrives in the queue.

9

Page 14: Data Sharing and Persistence With Symbian C++

It is the responsibility of the receiving thread to validate the data that is received. There is noin-built validation of the data passed in the messages other than basic type checking; that is,the data type is specified as the template argument.

Although it is possible for any number of threads to have the same message queue open, inpractice there are limitations that mean that the main use case for message queues is one-way,one-to-one communication between two threads. The reasons for this include:

• The communication is unicast in nature and so only one thread can receive eachmessage.

• Only one thread can do a blocking send at any one time because the kernel object hasonly one slot for a thread to wait for space to become available. Similarly, only onethread can do a blocking receive at any one time because the kernel has only one slotfor a thread to wait for data to arrive. A thread panics if it attempts to do a blockingsend or receive whilst another thread is occupying the corresponding waiting slot.

• To handle multiple threads doing non-blocking sends and/or receives, you would need touse a polling mechanism. However, polling is not a recommended solution on a Symbian OSsmartphone, because it can quickly run down the battery.

If you require two-way communication between two threads, it is possible to use a single messagequeue provided that the communication is strictly alternating – that is, Thread A sends a messageand Thread B reads that message before sending a message back. Thread A then reads thismessage before sending another message back, and so on. For any other type of two-waycommunication between two threads, you should set up two message queues, one for eachdirection.

Message queue APIThe main class is RMsgQueue, which is a handle to a message queue. It is a templated class,where the template parameter defines the message type. This must be a T type. Here is anexample of creating an anonymous global queue with five message slots and sending a message:

RMsgQueue<TInt> myQueue;

// Create an anonymous global message queue.User::LeaveIfError(myQueue.CreateGlobal(KNullDesC, 5));

TInt message = 6;

// Send a message consisting of a single integer.User::LeaveIfError(myQueue.Send(message));

Notice that in this example we are using the KNullDesC global constant to set the name to anempty string. This means that the global message queue is anonymous and we need to pass itshandle to the thread to which we want to send data. This is the recommended way of workingwith global queues.

Now let’s launch another process and pass the handle to the message queue:

// Create a child "Receiver" processRProcess receiverProc;_LIT(KProcessName, "Receiver");User::LeaveIfError(receiverProc.Create(KProcessName, KNullDesC));

10

Page 15: Data Sharing and Persistence With Symbian C++

11

// Pass the message queue handle in the child process's// environment slot 3.receiverProc.SetParameter(3, myQueue);

// Close the message queue.myQueue.Close();

// Start the child process.receiverProc.Resume();

When we pass the message queue handle in the child process’s environment slot, we can simplypass the message queue itself, because RMsgQueue is itself derived from RHandleBase. Whenwe close the message queue in the sending process, the handle in the receiving process keepsthe message queue open.

Here is an example of the receiver process opening the queue and receiving a message:

RMsgQueue<TInt> myQueue;

// Open the message queue using the handle passed in // environment slot 3.TInt err = myQueue.Open(3, EOwnerThread);if (KErrNone == err)

{TInt message;

// Read the message from the queue.User::LeaveIfError(myQueue.Receive(message));

// Close the message queue.myQueue.Close();}

Clearly this is an unrealistically simple example, but it demonstrates that the message queue APIis essentially straightforward. Further information about message queues can be found atdeveloper.symbian.com/main/documentation/sdl/symbian94/sdk/doc_source/guide/Base-subsystem-guide/e32/MessageQueue.

The Central RepositoryThe Central Repository is the Symbian OS mechanism for persistently storing application andsystem settings. By settings we mean configuration details, user preferences, etc. Otherapplications can be notified of changes to the settings and the settings are preserved, includingwhen the phone shuts down. The Central Repository is not designed for storing normal applicationdata, for which other mechanisms, such as a file (for example, for images or music) or an SQLdatabase (for example, for contacts), are more suitable.

The Central Repository is implemented using the Symbian OS client-server architecture and it isfully integrated into platform security. This gives it a major advantage compared to using SymbianINI files.

Page 16: Data Sharing and Persistence With Symbian C++

Figure 4: The Central Repository

Central Repository settings are stored in repositories (also known as key spaces). Each repositoryis identified by a UID, which must be allocated through Symbian Signed in the normal way (seewww.symbiansigned.com for further details). The UID is usually the secure ID (SID) of the owningapplication. It is possible for an application to own more than one repository, but this is notcommon, because each repository can store up to 232 key-value pairs (which are called settings).

Each setting is identified by an integer key and has a value that can be integer, float, text orbinary. You specify security policies that control who can read and write the settings in theinitialization file. You can also specify metadata that controls whether settings are included inbackup and RFS (restore factory settings) operations.

Initialization filesYou cannot create a repository through the API; instead, you create one by supplying aninitialization file. Smartphone manufacturers include the initialization files for applications andother executables in the \private\10202be9\ folder in ROM. Provided that they are SymbianSigned, after-market applications can also provide initialization files, and do so by providingthem for installation by the software installer. Currently, applications that are not Symbian Signedcannot use the Central Repository mechanism.

When applications (including those installed in ROM) are upgraded by a SIS file, their CentralRepository initialization files can be upgraded too.

Initialization files are named after the repository UID and a filename extension that depends onthe file format – .txt for plain text format (such as F0009396.txt) and .cre for the binaryformat (such as F0009396.cre). When using the plain text format, you must save the file inUTF-16 format.

The binary format provides faster access. However, unless the file is large, the plain text formatis generally preferred because it is easier to work with. But you can use the CentRepConv toolto convert a binary file to text for debugging, etc. There’s more on this in the ‘The CentRepConvconversion tool’ section, later in the booklet.

12

Page 17: Data Sharing and Persistence With Symbian C++

You need to pay particular attention to the format and syntax of the initialization file, becausethese are a common source of errors. Also, because you can’t change the security policy andmetadata after initialization, you need to think these through in advance. Try to think what willbe needed in the future and provide for it. A common approach is to specify security policies forreserved ranges of settings in order to cover future eventualities.

The initialization file has a number of sections. Here is an example initialization file, which isfollowed by brief explanations of the various sections under separate subheadings.

# This is a comment. 2000A970.txtcenrep # This is the first header lineversion 1 # This is the second header line

[owner]0x2000A970 # The SID of app that is responsible for backup/restore

[defaultMeta]0x03000000 # Enable backup/restore & restore factory settings (RFS)

# Default metadata settings for keys in the range 0x1000 to 0x20000x1000 0x2000 0x01000000 # Enable backup/restore, disable RFS

[platsec]# Default security policycap_rd=AlwaysPass cap_wr=WriteDeviceData

# Default security policy for a group of keys identified by key mask0x00000010 mask=0XFFFFFFF0 cap_rd=ReadDeviceData sid_wr = 0x2000A971

[main]# Syntax is: Key Type InitialValue <Metadata> <platsec>1 string "Unknown" 2 int 100 3 real 54.56

HeaderThe header contains two lines that are always the same. The version number refers to the fileformat version; currently this should be version 1.

You can use the hash (#) sign anywhere in the file to add comments.

[Owner]The [Owner]section is optional and is used to specify the SID of the application that owns therepository and is responsible for the backup and restore operation, if relevant. There’s more onbackup and restore in the ‘Backing up your repository’ section.

[defaultMeta]The [defaultMeta]section is also optional. If present, it specifies default metadata valueswhich may be overridden by individual metadata values assigned in the [main]section. Themetadata is a 32-bit number, of which the most significant 8 bits of the value are reserved forinternal use and the least significant 24 are made available for client metadata. Currently, thereare two reserved metadata bits that are published. These are:

• backup and restore (0x01000000)• RFS (restore factory settings) (0x02000000).

13

Page 18: Data Sharing and Persistence With Symbian C++

In our example file, there are two values in this section. The first applies to all of the settings towhich we don’t give a different metadata value. It is a bitwise AND of 0x01000000 (which meansenable backup and restore) and 0x02000000 (which means enable restore factory settings). Thesecond value applies to keys in the range 0x1000 to 0x2000 and it enables these settings tobe backed up and restored but stops them being restored to their factory settings during an RFSoperation. The factory settings are the original values specified in the [main] section.

You can also use a key mask to specify metadata values for a group of settings. There’s more onthis in the ‘Key masks’ section.

[platsec]The [platsec]section is compulsory and specifies default security policies, in terms of SIDs(which restrict access to identified applications) and/or capabilities (which enable sharing basedon capabilities). You must have a general default security policy, otherwise none of the settingswill be accessible. You can also specify security policies for ranges of settings, as we did in thedefault metadata section, or groups of settings by using a key mask. Like the default metadatasettings, the default security policies can be overridden on individual settings in the [main]section.

In our example we have two security policies in this section. The first applies to all of the settingsto which we don’t give a different security policy. It specifies that, by default, the settings can beread by all processes and can only be modified by processes that have the WriteDeviceDatacapability. The second security policy applies to a group of keys identified by a key mask/partialkey combination. It specifies that the ReadDeviceData capability is required to read thesesettings and that only a process that has a specific SID can modify them. There’s more on keymasks shortly.

Note that when you specify a SID, you can only specify up to three capabilities, rather than themaximum of seven when you do not specify a SID.

[main]The [main]section enables you to specify the data type and initial values (and optionallymetadata and security policies) for individual settings, ranges of settings or groups of settingsspecified with a key mask and partial key.

It is not necessary to specify all settings in the initialization file; it is possible to create settingsdynamically through the API. In fact, the [main]section can be empty. However, if you do specifysettings in the [main]section, you must define their initial values.

The syntax for the [main]section is as follows:

Key Type InitialValue <Meta> <platsec>

In our example we have simply specified initial values for keys 1, 2 and 3.

Key masksSometimes you may want to define more complex data structures, such as a 2D structure ofcolumns and rows or a 3D structure of tables, columns and rows. You can do this by using somebits in the 32-bit key to identify the table, some to identify the column and the rest the row.

To illustrate how this works, suppose you want to store four pieces of information about yourapplication’s most recently used files, such as file name, description, date last used and durationof use. You could create a 2D data structure within the repository by using two bits in the 32-bit

14

Page 19: Data Sharing and Persistence With Symbian C++

15

key to represent the fields (file name, description, date last used and duration of use) and theother bits to represent the row number. So 0x00000011 could be the key for the name of themost recently used file, 0x00000021 could be the key for its description, 0x00000031 couldbe the key for its last use date, 0x00000041 could be the key for its duration of use and0x00000012 could be the key for the name of the second most recently used file, etc., asshown in the following table.

Table 1: Example keys for storing information about most recently used files

On occasions you may want to refer to groups of settings without specifying them individuallyby key. We can do this using a key mask and a partial key. The key mask is a 32-bit hexadecimalnumber that represents a bit mask, in which binary 1s indicate mandatory values and binary 0sindicate non-mandatory ones. The partial key represents the pattern to be matched.

For example, continuing our recently used files example, suppose you want to set a platformsecurity setting on the recently used file name field. Here is the key mask:

0XFFFFFFF0

And here is the partial key:

0x00000010

Taken together, these specify all of the repository keys with the most significant 28 bits equal to0x0000001, which in this example are the keys representing ‘File name’ of the most recentlyused files.

You can use key masks to specify groups of settings in some of the API functions as well as inthe initialization file, as we saw in the example shown earlier in the ‘Initialization files’ section.

Central Repository APIThe Central Repository API has one class: CRepository. You open a repository by creating aCRepository object; there is no Open() function. For example:

// Open the repository.const TUid KUid = { 0xF0281D7B };CRepository* myRepository = CRepository::NewLC(KUid);

To open several repositories, you must create one CRepository object for each of them.

The CRepository object provides Get(), Set(), Create() and Delete() functions forworking with settings. Set() creates the setting if it doesn’t exist, so Create() is not generallyused. Note that Create() fails if the setting already exists.

File name Description Date Duration

1 0x00000011 0x00000021 0x00000031 0x00000041

2 0x00000012 0x00000022 0x00000032 0x00000042

3 0x00000013 0x00000023 0x00000033 0x00000043

4 0x00000014 0x00000024 0x00000034 0x00000044

5 0x00000015 0x00000025 0x00000035 0x00000045

6 0x00000016 0x00000026 0x00000036 0x00000046

Page 20: Data Sharing and Persistence With Symbian C++

Here is an example of using the Get() function to retrieve a file name stored in the CentralRepository:

TBuf<KMaxFileName> filename;const TUint32 KKey1 = 0x01;

// Retrieve the file name from the Central Repository.User::LeaveIfError(myRepository->Get(KKey1, filename));

StartTransaction() and CommitTransaction() are available for wrapping the writeoperations in a transaction. Symbian recommends that you use this feature when writing multipleinterdependent settings in order to avoid writing inconsistent data if one of the write operationsfails. Here is an example:

// Start a read-write transaction.User::LeaveIfError(myRepository->StartTransaction(

CRepository::EReadWriteTransaction));

// Causes FailTransaction() to be called if a Leave occurs.myRepository->CleanupCancelTransactionPushL();

const TUint32 KKey1 = 0x00000011;User::LeaveIfError(myRepository->Set(KKey1, iRecentFile.iName));

const TUint32 KKey2 = 0x00000012;User::LeaveIfError(myRepository->Set(KKey2, iRecentFile.iDesc));

// Commit the transaction – this writes the number of keys // that were successfully updated to keyInfo.TUint32 keyInfo;User::LeaveIfError(myRepository->CommitTransaction(keyInfo));

There are functions for finding settings, FindL(), FindNeqL(), FindEqL(), requestingnotification of changes to settings, NotifyRequest(), and restoring the default values,sometimes called factory settings specified in the initialization file Reset().

Backing up your repositoryAs we mentioned earlier, Symbian OS includes software to back up data to, and restore data from,a connected PC. You can also include your application’s repository in the backup. However, thereare some special details about how this is done.

1. In the backup registration file, include the SID of the Central Repository server, like this:

<?xml version="1.0" standalone="yes" ?> <backup_registration version="1.0">

<proxy_data_manager SID="0x10202be9" /><restore requires_reboot="no" />

</backup_registration>

2. In the [owner]section in the Central Repository initialization file, specify the SID of theapplication that owns the repository and is responsible for the backup and restore.

16

Page 21: Data Sharing and Persistence With Symbian C++

3. Use metadata values in the initialization file to specify the settings to be backed up. A settingis backed up if bit 25 of its metadata value is set. You can set this bit for the whole repositoryand groups of settings in the [defaultMeta] section or for individual settings using themetadata field in the [main] section.

The CentRepConv conversion toolCentRepConv is an emulator tool that converts Central Repository initialization files from theplain text format to the binary format and vice versa.

Run the tool from the eshell prompt in the Windows emulator. Note that file paths are SymbianOS paths, not paths in the PC’s native file system. The tool can tell whether it is a text to binaryconversion or vice versa from the filename extension.

The syntax for text to binary conversion is:

CentRepConv [-nowait] [-o output_path\rep_uid.cre] [input_path\] rep_uid.txt

The syntax for binary to text conversion is:

CentRepConv [-nowait] [-o output_path\rep_uid.txt] [input_path\] rep_uid.cre

The -nowait option is useful when the tool is run as part of an automated process, such as froma build script, as it stops the tool from waiting for an acknowledgement.

Memory chunksSymbian OS provides support for shared memory regions that can be accessed directly acrossmultiple threads and processes. These shared memory regions are known as memory chunks(usually shortened to chunks). When a chunk can be shared across processes, it is known as aglobal chunk and when shared across threads in the same process, it is known as a local chunk.You create a chunk and access existing chunks by using the RChunk API.

Global chunks have the advantage that they are a fast and efficient way of sharing data betweenprocesses. However, their use has a number of important caveats:

• The chunk may not be mapped at the same memory address in each process andtherefore storing ordinary pointers inside the chunk cannot be guaranteed to work. Ineach process you should express the address of a data item in the chunk as the chunk’sbase address plus an offset. You can use RChunk::Base() to obtain the base addressof a chunk within a given process.

• You must implement your own concurrency mechanism, for example, using a mutex toprevent more than one thread from updating data at the same time and semaphores toenforce the order of execution. Concurrency mechanisms can be complex and you need todesign and implement them well in order for them to work correctly, even though thebasic building blocks are provided. The introduction of SMP (symmetric multiprocessing)enabled versions of Symbian OS will make it even more important that your concurrencymechanisms are well designed.

• There is no built-in validation or security. For example, you need to check that a pointerdoes in fact point to data within the chunk, otherwise the thread will panic. If you areusing the chunk to share data with code that you do not trust, you must not dereferenceany pointers without validating that they refer to an expected and reasonable location,and must never call virtual methods on shared objects. It is much safer to communicatewith untrusted code via the client-server architecture.

17

Page 22: Data Sharing and Persistence With Symbian C++

18

Nevertheless, global chunks can sometimes be a useful solution, particularly when you need toshare large data structures between different parts of your own code.

The term shared memory chunk generally refers to chunks that are used for sharing data betweena user-side and a kernel-side process and are typically used by device drivers. The details ofusing shared memory chunks differ from local and global chunks. However, the caveats, includingthe need to be careful to synchronize access to the chunk through mechanisms such as mutexes,remain the same.

Further information about the use of memory chunks can be found atdeveloper.symbian.com/main/documentation/sdl/symbian94/sdk/doc_source/guide/Base-subsystem-guide/e32/MemoryManagement/MemoryAllocationOverview.guide.html.

ConclusionSymbian OS provides a variety of mechanisms for sharing data between threads and processesand it provides the SQL service and Central Repository for persisting application data and settingsrespectively.

This booklet has introduced four of these mechanisms and touched upon the use of memorychunks. The amount of space allocated in this booklet to each these mechanisms does notnecessarily reflect their relative importance. Symbian SQL and the Central Repository are bothcovered in some detail because the former is new and the latter has some setup details that youneed to understand in order to take advantage of its features. Publish and Subscribe and messagequeues are covered more briefly because their usage is relatively straightforward and Publishand Subscribe is already well documented in the public domain.

Page 23: Data Sharing and Persistence With Symbian C++

New from

Common Design Patterns for Symbian OS: The Foundations of Smartphone Software

Multimedia on Symbian OS: Inside the Convergence Device

Common Design Patterns for Symbian OSintroduces the common design patterns usedto implement a variety of applications andservices on Symbian OS. The book describespatterns based on the architectural elementsof Symbian OS and discusses how patternssuited for desktop software must be adaptedor even avoided on a mobile platform.

Combining the insights and experience ofsubject experts within Symbian and thethird-party developer community, this bookwill be an invaluable reference for anyoneworking with multimedia on Symbian OS.The authors provide details of the nativeC++ APIs for accessing camera, video,audio, image manipulation and radio tunerfunctionality, and discuss best practice,tips and tricks.

Symbian Press: developer.symbian.com/books

Page 24: Data Sharing and Persistence With Symbian C++

New from

Quick Recipes on Symbian OS

Games on Symbian OS: A Handbook for Mobile Development

This book aims to make it easier to developapplications by describing a number ofcommon programming tasks and providingclear explanations of how to complete them.The recipes are divided by technology,including graphics, multimedia, location-basedservices, networking, telephony, connectivityand messaging.

Full sample code is available for download, soit can be used as a starting point in your ownprojects.

This book forms part of the TechnologySeries from Symbian Press. It describesthe key aspects of the mobile gamesmarketplace, with particular emphasis oncreating games for smartphones based onSymbian OS v9.x.

It also looks at C/C++ Standards supportavailable for developers porting games toSymbian OS, how to write for the N-Gageplatform, and coding for runtimes such asJava ME and Flash Lite.

Symbian Press: developer.symbian.com/books

Page 25: Data Sharing and Persistence With Symbian C++

from

Developing Software for Symbian OS, Second Edition

Symbian OS C++ for Mobile Phones, Volume 3

This second edition of Developing Softwarefor Symbian OS helps software developersnew to Symbian OS to create smartphoneapplications. The original book has beenupdated for Symbian OS v9 and nowincludes a new chapter on applicationsigning and platform security, and updatesthroughout for Symbian OS v9 and changesto the development environment.

The latest edition of Richard Harrison’sexisting bestsellers draws on theexperience of Symbian’s own engineers tohelp you become an effective Symbian OSdeveloper.

If you’ve programmed in C++ at any leveland wish to develop software for Symbiansmartphones, this book gives you athorough grounding in writing C++applications for Symbian OS v9.

Page 26: Data Sharing and Persistence With Symbian C++

from

For all Symbian C++ developers:Symbian OS Communications Programming, 2nd Editionby Iain Campbell

S60 Programming - A Tutorial Guideby Coulton & Edwards

Symbian OS Explainedby Jo Stichbury

Symbian OS Internalsby Jane Sales

Symbian OS Platform Securityby Craig Heath

Smartphone Operating System Concepts with Symbian OS by Mike Jipping

Accredited Symbian Developer Primerby Jo Stichbury & Mark Jacobs

Page 27: Data Sharing and Persistence With Symbian C++

from

Published Booklets

.NET Development on S60A Guide to P.I.P.S.Carbide.c++ v1.3Coding StandardsCoding TipsCoverity Prevent on Symbian OS (SDN++ only)Creating Location-Aware ApplicationsEssential S60 - Developers’ GuideGetting StartedGetting to MarketJava ME on Symbian OSLocalization (SDN++ only)Performance TipsPlatform Security for allQuick Recipes TasterReady for ROM

Translated Booklets

Chinese RussianJapanese PersianKorean ItalianSpanish

Page 28: Data Sharing and Persistence With Symbian C++

DatasharingandpersistEnce

Using Symbian OS

Symbian OS provides various methods for sharing andpersisting data securely. This booklet provides anintroduction to four of these mechanisms (Symbian SQL,Publish and Subscribe, message queues and the CentralRepository). The booklet aims to help you get started usingthese services and to know when to use each one.

Data Sharing and Persistence is part of the Using Symbian OS series, designed to provide information in ahandy format to Symbian developers.

Symbian PressSymbian Press publishes books designed tocommunicate authoritative, timely, relevant andpractical information about Symbian OS and relatedtechnologies. Information about the Symbian Pressseries can be found at developer.symbian.com/books

Why? What? Where? How?