Symbian3/SDK/Source/GUID-E87018CD-01B4-5886-87FC-CD25EE90587D.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Fri, 11 Jun 2010 12:39:03 +0100
changeset 8 ae94777fff8f
parent 7 51a74ef9ed63
child 13 48780e181b38
permissions -rw-r--r--
Week 23 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 2714, Bug 462.

<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
<!-- This component and the accompanying materials are made available under the terms of the License 
"Eclipse Public License v1.0" which accompanies this distribution, 
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
<!-- Initial Contributors:
    Nokia Corporation - initial contribution.
Contributors: 
-->
<!DOCTYPE concept
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
<concept xml:lang="en" id="GUID-E87018CD-01B4-5886-87FC-CD25EE90587D"><title>Central Repository Transactions</title><prolog><metadata><keywords/></metadata></prolog><conbody><p>This topic describes the concepts of Central Repository transactions. </p> <section><title>Overview of transactions </title> <p>In a typical use case, a repository is accessed by several different applications for different purposes such as reading, updating, caching and backing up. These applications are regarded as having a client-server relationship with the repository. When multiple applications can access a repository there is a danger of concurrent write operations corrupting the data. To prevent this, applications access repositories within sessions and perform operations on a repository within subdivisions of a session called transactions. The concept of a transaction is borrowed from database programming and is designed to ensure that only one application can modify a repository at any one time. Operations performed within a transaction are virtual, operating on a copy of the repository, until the transaction is successfully committed and the actual repository is modified. Transactions conform to a model which prevents them from being committed concurrently, so maintaining data integity. </p> <p>Only the following operations are permitted within a transaction: </p> <ul><li id="GUID-A1CFE73C-6248-5B8E-A5F8-5125786EAF64"><p>Find() </p> </li> <li id="GUID-4D0AEFB5-FB08-591F-BA24-098E832B6FE0"><p>Get() </p> </li> </ul> <ul><li id="GUID-6001550D-DC06-5767-A03C-F6677D895ECF"><p>Set() </p> </li> <li id="GUID-28F16F3E-502D-52C1-A157-621EE4307466"><p>Create() </p> </li> <li id="GUID-9E98BC2F-5E94-51EA-8FE7-DDADE388AE21"><p>Delete() </p> </li> <li id="GUID-42BC1D3F-1CE7-5F76-8B9F-9276892D86BC"><p>Move() </p> </li> </ul> <p>Transactions are either synchronous or asynchronous. As the programmer you are responsible for avoiding errors such as beginning a transaction within a transaction which will cause a leave. You do this by conforming to a transaction model. </p> <p>The recommended transaction model is the optimistic non-serialised transaction model. It works on the principle that any number of clients may start a transaction at the same time, but as soon as one transaction is committed, any other transactions fail and must be started again. </p> <p>A session is in various states: </p> <ul><li id="GUID-F0C23BCF-6528-5112-AB35-BEA53D7EA5EF"><p>Not in transaction </p> </li> <li id="GUID-27922FAA-BF3F-5C06-9810-FE20C41474E1"><p>Active </p> </li> <li id="GUID-720E56F0-477D-5C4E-8FA3-7EEABDE0E718"><p>Failed </p> </li> </ul> <p>An asynchronous transaction involves two other states: </p> <ul><li id="GUID-17470F86-6FE8-5998-B7CA-546988BDE132"><p>Pending start </p> </li> <li id="GUID-7AB3E6B9-51C6-56ED-82E8-FF1A1805C54E"><p>Pending commit </p> </li> </ul> </section> <section><title>Synchronous transactions </title> <p>A synchronous transaction has the following structure. </p> <ul><li id="GUID-DE7AA608-AC0C-53BF-A009-3D179621193C"><p>A session is initially in the state Not in transaction. </p> </li> <li id="GUID-178E4E88-02C6-5869-B344-514C14FBDB4F"><p>Call the synchronous form of <xref href="GUID-2FE14318-A0C6-37F9-A359-85D353D94F68.dita"><apiname>StartTransaction()</apiname></xref> with the single parameter EConcurrentReadWriteTransaction. </p> </li> <li id="GUID-91D3A638-114B-5DCA-8FB0-35B554797194"><p>The session changes state to Active. </p> </li> <li id="GUID-C32289CB-8EA9-53E0-84DD-881FCDC5FF99"><p>Manipulate the repository with the functions <xref href="GUID-890C741F-EC69-30E3-AA89-CE35B3DE481F.dita"><apiname>Get()</apiname></xref> <xref href="GUID-2F459F8B-0464-33BF-BB95-DF0648A5C6ED.dita"><apiname>Set()</apiname></xref> <xref href="GUID-3D9FBB4B-907F-33BC-9C90-5A896FBEE290.dita"><apiname>Find()</apiname></xref> etc covered above. </p> </li> <li id="GUID-2F9FA0A5-7624-5300-819D-45562AF5FFDA"><p>The session continues in the Active state. The changes to the repository are cached but not actually applied during the Active state. You then either revoke or persist the changes. </p> </li> <li id="GUID-39F7530F-E9D9-5938-B9EB-B0AF8768E16F"><p>To revoke the changes, call <xref href="GUID-E7D1327D-70BF-380E-8798-455FD9F4AAE0.dita"><apiname>CancelTransaction()</apiname></xref>  </p> </li> <li id="GUID-B21F7C3F-E960-571A-A98E-933B96FA14D0"><p>The session returns to Not in transaction. </p> </li> <li id="GUID-6C4EF9E4-CE0A-542B-A564-72B6FF2BECB1"><p>To persist the changes, call the synchronous form of <xref href="GUID-DC938A94-1C71-3D9D-A4C0-45D5655F9F3A.dita"><apiname>CommitTransaction()</apiname></xref> with the parameter <xref href="GUID-A67CA4BD-6F1F-3B0D-962C-4A78BBE80402.dita"><apiname>aKeyInfo</apiname></xref> of type <xref href="GUID-F58A1C0D-1B36-37EA-8012-1C74B2D12CAD.dita"><apiname>TUint32</apiname></xref> This function returns success or an error message and its parameter holds information about the transaction. On success, the parameter holds the number of settings which were changed. On failure, the parameter holds the settings which caused failure in the form of a key or partial key. </p> </li> <li id="GUID-FD7629FE-C6AF-5F65-9376-353ADD2B87F7"><p>On success the session returns to Not in transaction. On failure it enters the Failed state. When a transaction fails, the operations already performed are discarded and no subsequent operations can reverse the failure. </p> </li> <li id="GUID-0BBDE613-761D-54F2-894B-3BEEAB587A95"><p>If the reason for failure was the success of another transaction, the error message is <xref href="GUID-CF080900-A9A4-391E-AC95-B93EBFB23DE3.dita"><apiname>KErrLocked</apiname></xref> and the session is Not in transaction. You try the same sequence of function calls until you get a successful commit. </p> <p>If there was some other reason for failure you must close the transaction yourself. To do this, either call <xref href="GUID-E7D1327D-70BF-380E-8798-455FD9F4AAE0.dita"><apiname>CancelTransaction()</apiname></xref> or else call <xref href="GUID-DC938A94-1C71-3D9D-A4C0-45D5655F9F3A.dita"><apiname>CommitTransaction()</apiname></xref> a second time. </p> <p>There is sometimes reason to fail the transaction deliberately by calling <xref href="GUID-D4178000-A2A4-3B22-B984-530DD5EC75EE.dita"><apiname>FailTransaction()</apiname></xref> For instance you might want to generate failure after an unsuccessful <xref href="GUID-890C741F-EC69-30E3-AA89-CE35B3DE481F.dita"><apiname>Get()</apiname></xref> operation and then cancel the transaction. </p> </li> </ul> <fig id="GUID-B2011974-4A4F-58B4-BDCD-CAFBAC4E52A7"><title>
             Synchronous transaction state diagram 
          </title> <image href="GUID-66E0B7F2-DEB4-5326-9DE0-5C0E253568AF_d0e351163_href.png" placement="inline"/></fig> </section> <section><title>Asynchronous transactions</title> <p>Synchronous transactions have the disadvantage that a busy server may block the client thread before any action takes place. To avoid this problem you can use the slightly more complicated asynchronous transactions. An asynchronous transaction has the same structure as a synchronous one except that there are two new states Pending Start and Pending Commit where a transaction waits until the server is ready to communicate with it. The transition from Not in transaction to Active now proceeds like this. </p> <ul><li id="GUID-A90153AE-A050-5721-9513-DD9753B1DF61"><p>A session is initially in the state Not in transaction. </p> </li> <li id="GUID-1F494795-6391-5A0E-B057-820602C90233"><p>Call the asynchronous form of <xref href="GUID-2FE14318-A0C6-37F9-A359-85D353D94F68.dita"><apiname>StartTransaction()</apiname></xref> with the parameters <xref href="GUID-27A4E547-66EA-3F07-943C-171FAB9EE99D.dita"><apiname>EConcurrentReadWriteTransaction</apiname></xref> and <xref href="GUID-8CC6A454-14EC-3059-B2F9-DC92B1D20F57.dita"><apiname>aStatus</apiname></xref> of type <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> This function returns void: success or the reasons for failure are determined from the state of <xref href="GUID-8CC6A454-14EC-3059-B2F9-DC92B1D20F57.dita"><apiname>aStatus</apiname></xref> after execution. </p> </li> <li id="GUID-C419B2EB-2D04-5B93-B01C-AB9107B52351"><p>The session changes state to Pending Start. Activity on the server will eventually promote the session to Active. </p> </li> <li id="GUID-5793F04F-4BED-5755-B678-A1CDF3AE1400"><p>Manipulate the repository with the functions <xref href="GUID-890C741F-EC69-30E3-AA89-CE35B3DE481F.dita"><apiname>Get()</apiname></xref>, <xref href="GUID-2F459F8B-0464-33BF-BB95-DF0648A5C6ED.dita"><apiname>Set()</apiname></xref>, <xref href="GUID-3D9FBB4B-907F-33BC-9C90-5A896FBEE290.dita"><apiname>Find()</apiname></xref> etc covered above. </p> </li> <li id="GUID-0210FDB7-FD3F-5A6F-90B0-B8DAD23960E3"><p>The session continues in the Active state. The changes to the repository are cached but not actually applied during the Active state. You then either revoke or persist the changes. </p> </li> <li id="GUID-617CA21B-89D5-5531-A9A4-83173FF66867"><p>To revoke the changes, call <xref href="GUID-E7D1327D-70BF-380E-8798-455FD9F4AAE0.dita"><apiname>CancelTransaction()</apiname></xref> This call has different effects depending on whether it was called in the Pending Start state or the Active state. If it was called in the Pending Start state it sets <xref href="GUID-8CC6A454-14EC-3059-B2F9-DC92B1D20F57.dita"><apiname>aStatus</apiname></xref> to <xref href="GUID-6F4A88DA-F54E-3848-9C32-942D6F5F4F3E.dita"><apiname>KErrCancel</apiname></xref>  </p> </li> <li id="GUID-57E59324-D623-5F0E-9954-B7B6C045C63E"><p>The session returns to Not in transaction. </p> </li> <li id="GUID-1E0463FC-81E0-574A-9585-11593FB31DD9"><p>To persist the changes, call the asynchronous form of <xref href="GUID-DC938A94-1C71-3D9D-A4C0-45D5655F9F3A.dita"><apiname>CommitTransaction()</apiname></xref> with the parameters <xref href="GUID-A67CA4BD-6F1F-3B0D-962C-4A78BBE80402.dita"><apiname>aKeyInfo</apiname></xref> of type <xref href="GUID-F58A1C0D-1B36-37EA-8012-1C74B2D12CAD.dita"><apiname>TUint32</apiname></xref> and <xref href="GUID-8CC6A454-14EC-3059-B2F9-DC92B1D20F57.dita"><apiname>aStatus</apiname></xref> of type <xref href="GUID-E0B34F3E-D4C4-3232-B8B1-7DB35B454646.dita"><apiname>TRequestStatus</apiname></xref> This function returns void. Its first parameter holds information about the transaction. </p> </li> <li id="GUID-87C8F64D-2FE3-53D3-956C-3211EF7B776B"><p>On success, the <xref href="GUID-8CC6A454-14EC-3059-B2F9-DC92B1D20F57.dita"><apiname>aStatus</apiname></xref> parameter holds the number of settings which were changed. On failure, the parameter holds the settings which caused failure in the form of a key or partial key. The <xref href="GUID-8CC6A454-14EC-3059-B2F9-DC92B1D20F57.dita"><apiname>aStatus</apiname></xref> parameter is set to success or failure. </p> </li> <li id="GUID-4DE0D798-4B73-5EA2-B4DE-2DEDCE6CE55A"><p>If the reason for failure was the success of another transaction, aStatus is set to <xref href="GUID-CF080900-A9A4-391E-AC95-B93EBFB23DE3.dita"><apiname>KErrLocked</apiname></xref> and the session is Not in transaction. You try the same sequence of function calls until you get a successful commit. </p> <p>If there was some other reason for failure you must close the transaction yourself. To do this, either call <xref href="GUID-E7D1327D-70BF-380E-8798-455FD9F4AAE0.dita"><apiname>CancelTransaction()</apiname></xref> or else call <xref href="GUID-DC938A94-1C71-3D9D-A4C0-45D5655F9F3A.dita"><apiname>CommitTransaction()</apiname></xref> a second time. </p> <p>There is sometimes reason to fail the transaction deliberately by calling <xref href="GUID-D4178000-A2A4-3B22-B984-530DD5EC75EE.dita"><apiname>FailTransaction()</apiname></xref> For instance you might want to generate failure after an unsuccessful <xref href="GUID-890C741F-EC69-30E3-AA89-CE35B3DE481F.dita"><apiname>Get()</apiname></xref> operation and then cancel the transaction. </p> </li> </ul> <fig id="GUID-70E4E2BC-3996-54B1-AC65-ECADFB4E66FE"><title>
             Asynchronous Transaction State Diagram 
          </title> <image href="GUID-D2CF64ED-0D85-5535-9A51-C127B10B07B2_d0e351327_href.png" placement="inline"/></fig> </section> <section><title>Cleanup </title> <p>There is a danger that a transaction might remain open for ever if it is opened by code which subsequently leaves. To avoid this possibility, the <xref href="GUID-849C6016-BDB1-39B0-A48E-3AA661E11811.dita"><apiname>CCentralRepository</apiname></xref> class has two functions which cause the cleanup stack to end the transaction in the event of a leave. <xref href="GUID-896BCACB-335C-3A77-9161-52EA711AA84C.dita"><apiname>CleanupCancelTransactionPushL()</apiname></xref>, also named <xref href="GUID-D27AD32E-1D1F-34C9-92ED-B1CFCFB1DC0B.dita"><apiname>CleanupRollbackTransactionPushL()</apiname></xref>, causes a leave to be followed by a call to <xref href="GUID-E7D1327D-70BF-380E-8798-455FD9F4AAE0.dita"><apiname>CancelTransaction()</apiname></xref>. <xref href="GUID-F9520CB0-266B-357D-997F-756787C5F549.dita"><apiname>CleanupFailTransactionPushL()</apiname></xref> causes a leave to be followed by a call to <xref href="GUID-D4178000-A2A4-3B22-B984-530DD5EC75EE.dita"><apiname>FailTransaction()</apiname></xref>. </p> </section> </conbody><related-links><link href="GUID-1C683226-C142-5C7B-BD20-060058352B08.dita"><linktext>Central Repository Guide</linktext> </link> <link href="GUID-724BA3CD-7648-51DF-9285-3AA7470987F4.dita"><linktext>Optimising Repository
                Access</linktext> </link> <link href="GUID-998DCA78-2488-5D6D-B5B3-D86C52F32823.dita"><linktext>Modifications to
                Keyspaces</linktext> </link> </related-links></concept>