diff -r 43e37759235e -r 51a74ef9ed63 Symbian3/SDK/Source/GUID-DFF9DFC5-1BE0-5CA2-A2B9-27FA2DECFF59.dita --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Symbian3/SDK/Source/GUID-DFF9DFC5-1BE0-5CA2-A2B9-27FA2DECFF59.dita Wed Mar 31 11:11:55 2010 +0100 @@ -0,0 +1,481 @@ + + + + + +Writing +an Active Backup Client TutorialA backup client application is often referred to as a data owner +as it owns the data. This section describes how to write an active backup +client which works with the Backup Engine and the Backup Server for data backup +and restore. +

Before you start, +you must understand:

    +
  • Backup +Engine Concepts introduce the backup and restore types.

  • +
  • Symbian +Backup and Restore architecture describes the two ways of data backup +and restore.

  • +
  • Active +Backup Client Architecture describes the components involved to do +active data backup and restore.

  • +
  • Symbian +Publish and Subscribe describes how to publish and subscribe events +using properties.

  • +
+

In an active backup +and restore, the Backup Engine calls the active backup client to supply the +data for the backup. Writing an active backup client means to:

    +
  • Create a user defined +class that has a data member pointer to conn::CActiveBackupClient.

  • +
  • Implement the conn::MActiveBackupDataClient interface.

  • +
+ + +Write an active backup client (data owner) class which must subscribe +for the KUidBackupRestoreKey property published by the backup +server. +When a backup server receives a request from a client (a host PC) for +a backup or a restore, it reads backup registration files for a list of data +owners (refer to step 3). It then calls the CSBEClient::SetBURModeL() function +with the registered types (base or incremental, full or partial). This function +signals start or completion of a backup or restore to all data owners. Data +owners must subscribe the following publish and subscribe property: + + +Key–KUidBackupRestoreKey defined in the epoc32\include\connect\sbdefs.h header +file. This key belongs to the KUidSystemCategoryValue category. + + +Value–TBURPartType or TBackupIncType. + + +The backup client must check the value of the property (flag) on startup, +in case the device is already in a backup or restore mode. A conn::CActiveBackupClient object +can only be created once the publish and subscribe flag has transitioned into +a backup or restore mode. The backup client can be deleted once the backup +or restore operation has finished. This releases valuable system resources. + CActiveBackupClient::ConfirmReadyForBURL() is called +to indicate that the backup client is ready for the data supply to the Backup +Engine. +class CReferenceActiveDataOwner : public CActive + { + // Methods +public: + static CReferenceActiveDataOwner* NewL(); + ~CReferenceActiveDataOwner(); + + // From CActive + void RunL(); + TInt RunError(TInt aError); + void DoCancel(); + +private: + CReferenceActiveDataOwner() + void ConstructL(); + void SubscribeToPSFlag(); + void ProcessBackupStateL(TInt aBackupStateValue); + + // Attributes +private: + //Active Backup Client + CActiveBackupClient* iActiveBackupClient; + + //The publish and subscribe flag from the Backup Engine + RProperty iProperty; + + //Pointer to the callback implementation + CReferenceCallbackImplementation* iCallbackImpl; + }; + +/** Subscribe to the publish and subscribe flag. + Call RunL() when the flag changes. +*/ +void CReferenceActiveDataOwner::SubscribeToPSFlag() + { + iStatus = KRequestPending; + iProperty.Subscribe(iStatus); + SetActive(); + } + +/** Check the flag in case the data owner has been started for a backup or restore, + or in case the publish and subscribe transition is missed. +*/ +void CReferenceActiveDataOwner::ConstructL() + { + // Set up the property to catch the flag. + TInt backupStateValue = 0; + iProperty.Attach(KUidSystemCategory, KUidBackupRestoreKey); + + // Process the mode change accordingly + iProperty.Get(backupStateValue); + ProcessBackupStateL(backupStateValue); + + // Add to the active scheduler + CActiveScheduler::Add(this); + + // Subscribe to the flag to catch transitions + SubscribeToPSFlag(); +} + +/** Create the CActiveBackupClient and the callback implementation + based on the flag. +@param aBackupStateValue the new backup state value +*/ +void CReferenceActiveDataOwner::ProcessBackupStateL(TInt aBackupStateValue) + { + TInt type = aBackupStateValue & KBURPartTypeMask; + + // Create the the CActiveBackupClient and the callback implementation if + // the device is in a backup or a restore mode. + if (type == EBURBackupFull || type == EBURRestoreFull || + type == EBURBackupPartial || type == EBURRestorePartial) + if (iCallbackImpl == NULL) + { + iCallbackImpl = CReferenceCallbackImplementation::NewL(); + } + if (iActiveBackupClient == NULL) + { + iActiveBackupClient = + CActiveBackupClient::NewL(iCallbackImpl); + } + } + + // Confirm the readiness of the active backup client. + if ((type == EBURBackupFull || type == EBURRestoreFull) || + ((type == EBURBackupPartial || type == EBURRestorePartial) && + iActiveBackupClient->DoesPartialBURAffectMeL())) + { + + .... // Things handled by a device vendor. + + //Inform the Backup Engine that the client is ready for data supply. + iActiveBackupClient->ConfirmReadyForBURL(KErrNone); + } + else + { + // CActiveBackupClient and the callback implementation + // if it is not an active backup. + if (iActiveBackupClient != NULL) + { + delete iActiveBackupClient; + iActiveBackupClient = NULL; + } + + // The callback implementation must be deleted after + // the CActiveBackupClient is deleted. + if (iCallbackImpl != NULL) + { + delete iCallbackImpl; + iCallbackImpl = NULL; + } + } + } + +/** When the flag changes, RunL() is called. +*/ +void CReferenceActiveDataOwner::RunL() + { + + TInt backupStateValue = 0; // re-set the flag value + + // re-subscribe to the flag to monitor future changes + SubscribeToPSFlag(); + + iProperty.Get(backupStateValue); + + // Process the mode change accordingly + ProcessBackupStateL(backupStateValue); + } + +... + + + +Implement conn::MActiveBackupDataClient to write +a callback handler. +The callback handler prepares the data to the Backup Engine for a backup +or a restore. For more information about each function, refer to the conn::MActiveBackupDataClient API +reference. The callback implementation must fulfill the following requirements: + + +The Initialise function is usually called before the actual backup or +restore function is called. For example, InitialiseGetBackupDataL() is +called before GetBackupDataSectionL(). The Initialise function +gives a chance to a device vendor to prepare the data before the actual data +supply. + + +In an incremental backup or restore, a snapshot is the dataset after +each incremental backup or restore. If MActiveBackupDataClient::AllSnapshotsSuppliedL() is +called, it means that all snapshots have been supplied to the conn::CActiveBackupClient. +If conn::CActiveBackupClient does not receive a snapshot, +it performs a base backup. + + +For a backup function, a TBool reference parameter +named aFinished is passed as an argument. This indicates +to the Backup Engine if all of the data for a backup is supplied. Setting +this to EFalse causes the Backup Engine to repeatedly call +the backup function for more data. + + +For a restore function, aFinished is passed from the +Backup Engine to indicate to the data owner if all of the restore data is +supplied. The Backup Engine sets aFinished to ETrue after +the final call of the restore function. + + +Any leaves in the callback are propagated over Inter-Processor Communications +(IPC) to the Backup Engine and potentially to the PC as errors. For this reason, +any internal calls must be trapped in the callback. + + +class CReferenceCallbackImplementation : + public CBase, + public MActiveBackupDataClient + { + // Methods +public: + static CReferenceCallbackImplementation* NewL(); + ~CReferenceCallbackImplementation(); + + // The following functions are from the MActiveBackupDataClient + void AllSnapshotsSuppliedL(); + void ReceiveSnapshotDataL(TDriveNumber aDrive, TDesC8& aBuffer, + TBool aLastSection); + TUint GetExpectedDataSize(TDriveNumber aDrive); + void GetSnapshotDataL(TDriveNumber aDrive, TPtr8& aBuffer, + TBool& aFinished); + void InitialiseGetBackupDataL(TDriveNumber aDrive); + void GetBackupDataSectionL(TPtr8& aBuffer, TBool& aFinished); + void InitialiseRestoreBaseDataL(TDriveNumber aDrive); + void RestoreBaseDataSectionL(TDesC8& aBuffer, TBool aFinished); + void InitialiseRestoreIncrementDataL(TDriveNumber aDrive); + void RestoreIncrementDataSectionL(TDesC8& aBuffer, TBool aFinished); + void RestoreComplete(TDriveNumber aDrive); + void TerminateMultiStageOperation(); + TUint GetDataChecksum(TDriveNumber aDrive); + + //The following two functions are for the proxy backup client only and + // Symbian provides a default implementation for each function. + void InitialiseGetProxyBackupDataL(TSecureId aSID, TDriveNumber aDrive); + void InitialiseRestoreProxyBaseDataL(TSecureId aSID, TDriveNumber aDrive); + +private: + CReferenceCallbackImplementation() {} + CMyABData* iSnapshot; + CMyABData* iData; + TBool iProxy; + TInt iOffset; + TInt iSourceSize; + TUint iFillChar; + TSecureId iID; + }; + +void CReferenceCallbackImplementation::AllSnapshotsSuppliedL() + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::AllSnapshotsSuppliedL()", + iID.iId); + } + +void CReferenceCallbackImplementation::ReceiveSnapshotDataL( + TDriveNumber aDrive, + TDesC8& aBuffer, + TBool /*aLastSection*/) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::ReceiveSnapshotDataL()", iID.iId); + // Create or append a buffer containing the snapshot + if (!iSnapshot) + { + iSnapshot = CMyABData::NewL(aDrive); + } + + iSnapshot->AddDataL(aBuffer); + } + +TUint CReferenceCallbackImplementation::GetExpectedDataSize(TDriveNumber /*aDrive*/) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::GetExpectedDataSize()", iID.iId); + + return iSourceSize; + } + +void CReferenceCallbackImplementation::GetSnapshotDataL( + TDriveNumber /*aDrive*/, + TPtr8& aBuffer, + TBool& aFinished) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::GetSnapshotDataL()", iID.iId); + aBuffer.Append(KABTestSnapshot()); + + aFinished = ETrue; + } + +void CReferenceCallbackImplementation::InitialiseGetBackupDataL(TDriveNumber /*aDrive*/) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::InitialiseGetBackupData()", iID.iId); + iOffset = 0; + + if (!iSnapshot) + { + iFillChar = 66; + } + else + { + iFillChar = 73; + } + } + +void CReferenceCallbackImplementation::GetBackupDataSectionL( + TPtr8& aBuffer, + TBool& aFinished) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::GetBackupDataSectionL()", iID.iId); + + FillBuffer(aBuffer, aFinished); + } + +void CReferenceCallbackImplementation::InitialiseRestoreBaseDataL(TDriveNumber aDrive) + { + __LOG("CReferenceCallbackImplementation::InitialiseRestoreBaseDataL()"); + + iData = CMyABData::NewL(aDrive); + } + +void CReferenceCallbackImplementation::RestoreBaseDataSectionL( + TDesC8& aBuffer, + TBool aFinished) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::RestoreBaseDataSectionL()", iID.iId); + + // append a buffer containing the base data + iData->AddDataL(aBuffer); + + if (aFinished) + { + ValidateRestoredData(); + + delete iData; + iData = NULL; + } + } + +void CReferenceCallbackImplementation::InitialiseRestoreIncrementDataL(TDriveNumber aDrive) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::InitialiseRestoreIncrementDataL()", iID.iId); + if (!iSnapshot) + { + User::Leave(KErrCorrupt); + } + + if (!iData) + { + iData = CMyABData::NewL(aDrive); + } + } + +void CReferenceCallbackImplementation::RestoreIncrementDataSectionL( + TDesC8& aBuffer, + TBool aFinished) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::RestoreIncrementDataSectionL()", iID.iId); + + iData->AddDataL(aBuffer); + + if (aFinished) + { + ValidateRestoredData(); + + delete iData; + iData = NULL; + } + } + +void CReferenceCallbackImplementation::RestoreComplete(TDriveNumber /*aDrive*/) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::RestoreComplete()", iID.iId); + } + +void CReferenceCallbackImplementation::TerminateMultiStageOperation() + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::TerminateMultiStageOperation()", iID.iId); + // We also don't do anything here until we start testing multipart? + } + +TUint CReferenceCallbackImplementation::GetDataChecksum(TDriveNumber /*aDrive*/) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::GetDataChecksum()", iID.iId); + return 0; + } + +void CReferenceCallbackImplementation::InitialiseGetProxyBackupDataL( + TSecureId aSID, + TDriveNumber /*aDrive*/) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::InitialiseGetProxyBackupDataL()", iID.iId); + __LOG2("[0x%08x]: Proxy data about to be requested for SID 0x%08x", iID.iId, aSID.iId); + iProxy = ETrue; + iOffset = 0; + + iFillChar = 80; // 'P' + } + +void CReferenceCallbackImplementation::InitialiseRestoreProxyBaseDataL( + TSecureId aSID, + TDriveNumber aDrive) + { + __LOG1("[0x%08x]: CReferenceCallbackImplementation::InitialiseRestoreProxyBaseDataL()", iID.iId); + __LOG2("[0x%08x]: Proxy data about to be restored for SID 0x%08x", iID.iId, aSID.iId); + iProxy = ETrue; + iData = CMyABData::NewL(aDrive); + } +... + + +Create a backup registration file to set attribute values for the data +owner application. +The Backup Engine parses backup registration files to get the data own +list. The list includes details of data owners and data for backup and restore. +Create the file using a text editor and save it as backup_registration.xml under +the private folder of the data owner application on the Symbian device. Refer +to Backup Registration +Files for more information. + + + process_name is the name of the data owner application. + + + active_type is set to activeonly for +an active backup. + + + supports_incremental can be set to false to +disable the incremental backup support from the active backup client. + + +<!-- backup_registration.xml file for referencetestdataowner.exe --> + +<?xml version="1.0" standalone="yes"?> + +<backup_registration version="1.0"> + <active_backup process_name = "referencetestdataowner.exe" + active_type = "activeonly" + requires_delay_to_prepare_data = "yes" <!--deprecated--> + supports_incremental = "yes"> + </active_backup> + + <restore requires_reboot = "no"/> <!--Currently only support no--> +</backup_registration> +

Finally, test the data owner application. The logging information +appends to the securebackup.txt log file. To enable the +log generation, the C:\logs\connect directory must be +created on the device.

+
+
+
\ No newline at end of file