A 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.
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); } ...
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); } ...
<!-- 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.