Create Backup for Rollback - Separate CA?
Posted 24 June 2009 - 08:12
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):
//copy existing file(s) to SUPPORTDIR
//(using the MSI property SUPPORTDIR!)
There is also a rollback CA:
//delete modified file(s)
//restore file(s) from the backup (SUPPORTDIR)
//delete backup files
and a commit CA:
//delete backup files (SUPPORTDIR)
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"?
Posted 24 June 2009 - 10:36
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:
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.
Posted 24 June 2009 - 14:01
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.
Posted 25 June 2009 - 09:37
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.
Posted 25 June 2009 - 09:50
|First, consider putting the modifications in MyCA_Commit. MyCA_Rollback should then only remove the backup.|
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.
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.
- 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.
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.