Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

Create Backup for Rollback - Separate CA?


6 replies to this topic

Matthias1967

Matthias1967
  • Full Members
  • 92 posts

Posted 24 June 2009 - 08:12

Hello,

I am writing some custom actions that do change the system (modify files already present).
In order to ensure that rollback is possible, my code looks basically like this (I am using InstallScript, but the issue is language-independent):

CODE
function MyCA(hMSI)

begin
//get CustomActionData

//copy existing file(s) to SUPPORTDIR
//(using the MSI property SUPPORTDIR!)

//do modifications
end;


There is also a rollback CA:

CODE

function MyCA_Rollback(hMSI)

begin
//get CustomActionData

//delete modified file(s)

//restore file(s) from the backup (SUPPORTDIR)

//delete backup files
end;


and a commit CA:
CODE

function MyCA_Commit(hMSI)

begin
//get CustomActionData

//delete backup files (SUPPORTDIR)

end;


However, I am thinking about what happens if the backup command (i.e. copying the existing file(s) to SUPPORTDIR) fails. As far as I have understood the issue, rollback is started, the rollback CA deletes the files that should have been modified (or not yet modified), then it cannot restore the backup files because backup has failed. As a result, I would get a corrupted system (missing files) just because backup failed.

As a workaround, I think I need two additional CAs: MyCA_Backup that only does the backup and MyCA_BackupRollback deleting the backup files (basically the same code as MyCA_Commit).

This makes 5 CAs instead of 3 - plus the CustomActionData setters 10 (ten) CAs in total.

Is there an "easier" solution, or is my approach too "paranoid"?


Zweitze

Zweitze
  • Full Members
  • 522 posts

Posted 24 June 2009 - 10:36

The solution is easy. You may have noticed that Rollback CAs are scheduled just like normal Deferred CAs, between InstallInitialize and InstallFinalize. In other words, there is no decidated sequence for all Rollback activities.

Well: The Rollback CA will be called, when an error occurs in an actions AFTER the Rollback CA. It will NOT be called when an error occurs in an action BEFORE the Rollback CA.

So, in your project MyCA should be a Deferred CA, and you sequence should look like:

InstallInitialize
[...]
MyCA_Deferred
MyCA_Rollback
[...]
MyCA_Commit
[...]
InstallFinalize

Regardless of that, it wouldn't hurt to be paranoid and program defensively in the Rollback. After all, something went wrong (out of memory? out of disk?) and the situation is tense. When you did that, consider to put MyCA_Rollback just before MyCA_Deferred. In that case, the rollback is also called when the error occurs during MyCA_Deferred.

Matthias1967

Matthias1967
  • Full Members
  • 92 posts

Posted 24 June 2009 - 14:01

Hello Zweitze,

My sequence looks similar to your example, except that I have scheduled MyCA_Rollback before MyCA_Deferred. Indeed, MyCA is a deferred CA, and I am aware about the how rollback proceeds.

I put MyCA_Rollback before MyCA in order to call it if an error occurs in MyCA.
So in a sequence with 3 coded CAs (plus 3 setters), I may get the problem I asked about, namely that backup (part of MyCA) fails and then the rollback CA corrupts the system.

Regards,

Matthias

Zweitze

Zweitze
  • Full Members
  • 522 posts

Posted 25 June 2009 - 09:37

There's no problem scheduling MyCA_Rollback before MyCA_Deferred, except for one reason: Now the rollback CA will also be called when MyCA_Deferred fails. Which means that your backup may not be complete, therefore the Rollback must be able to detect whether the backup is valid and should be used.

You have two alternatives.
First, consider putting the modifications in MyCA_Commit. MyCA_Rollback should then only remove the backup. This alternative is only valid when you are sure that the modification will succeed - MyCA_Commit cannot fail. The last moment for that test is MyCA_Deferred, so that CA should create a backup and verify that the modifications will be valid.
The second alternative is along your opening post. When you are not able do validate a backup, you should split MyCA_Deferred into a backup CA and modification CA, and MyCA_Rollback into a Restore CA and a Cleanup CA.

Stefan Krueger

Stefan Krueger

    InstallSite.org

  • Administrators
  • 13,269 posts

Posted 25 June 2009 - 09:50

QUOTE
First, consider putting the modifications in MyCA_Commit. MyCA_Rollback should then only remove the backup.
Caution: if rollback is disabled on this machine (e.g. because disk space is low) then any rollback or commit actions will be skipped, i.e. the file will not be modified.

Your rollback CA should check if a backup is available in SUPPORTDIR before it deletes the modified file. You may also want to check whether file was actually modified (if not you don't need to restore the backup). Note that depending on what the cause for the failure is, it might be possible to delete the existing file but still be impossible to copy or move the backup. But I think that's not a typical situation.

VBScab

VBScab
  • Full Members
  • 436 posts

Posted 25 June 2009 - 10:51

QUOTE (Stefan Krueger @ 2009-06-25 08:50)
But I think that's not a typical situation.

Those situations are generally the ones which bite you unexpectedly. My philosophy for these scenarios is: always assume that the worst will happen and code accordingly.
- Don't know why 'x' happened? Want to know why 'y' happened? ProcMon will tell you.
- Try using http://www.google.com before posting.
- I answer questions only via forums. Please appreciate the time I give here and don't send me personal emails.

Zweitze

Zweitze
  • Full Members
  • 522 posts

Posted 25 June 2009 - 14:55

QUOTE (Stefan Krueger @ 2009-06-25 08:50)
Caution: if rollback is disabled on this machine (e.g. because disk space is low) then any rollback or commit actions will be skipped, i.e. the file will not be modified.

I can't believe it but the documentation agrees with you: When property [RollbackDisabled] is set, Commit CAs will be skipped but installation will succeed anyway. I learnt something new today!

Thanks for pointing this out.