This document describes how Backup Manager can be extended by using system hooks.
Hooks allow the alteration of certain aspects of the key Backup Manager operations. This can be used to add features such as date/time-stamping backups as they're modified or restored, or compressing/decompressing backup files.
Backup Manager has 10 different hooks. Each hook allows a routine to modify a particular operation. The following is a list of the hooks and an example of how each can be used:
Hook# | Operation | Usage example |
---|---|---|
1 | Creation of a new backup (just before the operation actually takes place) | Compression of the backup file |
2 | Creation of a new backup (just after the operation takes place) | Addition of extended backup data as soon as the backup is created |
3 | Updating of a backup | Compression of the backup file |
4 | Restoration of a backup or version | Decompression of the backup file as it is restored |
5 | Deletion of a backup | Removal of data (created by an external hook or shell) specific to the backup being deleted |
6 | Creation of a backup version | Creation of any custom data related to the new version |
7 | Changing of a version's comment | Updating of any custom data related to the version |
8 | Deletion of a version | Removal of any custom data related to the version |
9 | Occurrence of any error in an operation (before any action is taken by Backup Manager's error handler) | Customization of error handler behavior |
10 | Occurrence of an unknown (unexpected) error in an operation | Handling of custom error codes for externally implemented features |
Note: newbu is the only routine that has two hooks (#1 and #2) associated to it. Hook #1 is mainly used for modifying the backup file as it gets backed up. Hook #2 is mainly used for adding new data to the backup database for that backup. These two hook routines should be used as indicated here. During hook #1, it is too early to add backup information to the backup database, and during hook #2, it is too late to modify the backup file, because it has already been backed up.
A list named bhooks is used to register hooks with the Backup Manager system. The list contains a command to execute for each hook.
bhooks does not exist in a default installation, but it can be created by any program while the backup database is open. The list should have ten elements, all of them strings. Each element contains the code to execute for a particular hook. Elements representing unused hooks should be null strings.
To register a hook routine, the appropriate code simply has to be placed in the proper element in the bhooks variable. If you are writing a program that automatically installs a hook routine, it would be a good idea to check whether code already exists for the hook your program is going to install, and ask the user first if that code should be replaced. Depending on what the already installed hooks do, replacing a hook for another hook without the user's permission could cause bad things to happen.
Important: The database must be open (i.e., openbd must be called) before bhooks is modified.
Here's an example of a bhooks variable that calls the program myhook for hooks 1, 3, 4, and 6, with a parameter that indicates the hook number. (Such a parameter is not required, but allows the hook routine to know which operation is taking place.) All other hooks are currently unused; that is, they have no hook routines associated with them yet.
{"myhook(1)","","myhook(3)","myhook(4)","","myhook(6)","","","",""}
The following variables are used for communication between hook routines and the Backup Manager system routines:
The specific data contained in the variables depends on the hook.
bhin is always a list. It contains information about the operation, usually the parameters passed to the system Backup Manager routine that is calling the hook routine.
Hook # | Format |
---|---|
1 | LIST: {orig. path, act. path, bkup. file, 0, stored away?} |
2 | LIST: {orig. path, act. path, bkup. file, bkup. index, stored away?} |
3 | LIST: {orig. path, act. path, bkup. file, bkup. index} |
4 | LIST: {orig. path, act. path, bkup. file, bkup. index, vers. index, overwrite? |
5 | LIST: {orig. path, orig. path, bkup. file, bkup. index, delete stored-away?} |
6 | LIST: {orig. path, act. path, bkup. file, bkup. index, vers. comment, vers. index} |
7 | LIST: {orig. path, orig. path, bkup. file, bkup. index, vers. comment, vers. index} |
8 | LIST: {orig. path, orig. path, bkup. file, bkup. index, vers. index} |
9 | LIST: {error number, backup file path, display error dlg?, pass other errors?} |
10 | LIST: {error number, backup file path, display error dlg?, pass other errors? |
bhout is used by hook routines to return data back to their calling routines. The bhout variable has different purposes depending on which hook routine is used.
Hook # | Format |
---|---|
1 | STRING: Actual file |
2 | Not used |
3 | STRING: Actual file |
4 | STRING: Actual file |
5 | Not used |
6 | STRING: Actual file |
7 | STRING: Ver. comment to use |
8 | Not used |
9 | NUM: Value of errornum to assume |
10 | NUM: Value of errornum to assume |
bhout2 is used by some hooks to return additional data back to the calling program.
Hook # | Format |
---|---|
1 | Not used |
2 | Not used |
3 | Not used |
4 | Not used |
5 | Not used |
6 | STRING: Ver. comment to use |
7 | Not used |
8 | Not used |
9 | STRING: Error message text |
10 | STRING: Error message text |
bhtemp is a reserved variable for hook routine use. Hook routines may use this variable for any purpose (for instance, to hold a temporary copy of a backup as it is being compressed). The bhtemp variable is automatically deleted the next time a hook routine is called, or when the backup database is closed.
This example shows how to write a hook routine that automatically records the last modification date and time for each backup in the backup database (for TI-89 AMS 2.08 or higher with hardware version 2). The date/time stamp is written each time a backup is created or modified.
The first step is to decide where the hook routine will be stored and what command will be used to execute it. For this example, the hook routine will be named hdtstamp and stored in the ωbman3 folder.
The second step is to write the hook routine. Since we are adding date/time stamps to modified or newly created backups, we want to have the date/time stamp added during hooks 2 (creation of a new backup) and 3 (updating of an existing backup).
So that we know which hook is taking place, we will have our routine take an input parameter (h) giving the number of the hook routine.
The code for the hook routine looks like this:
:hdtstamp(h)
:Prgm
:©Backup Manager 3 hook
:©Add date/time stamp to created/modified backup files
:
:©Check hook (only take action on hooks 2 and 3)
:If h=2 or h=3 Then
: ©Find the database field for date/time stamps
: ©If it's not defined, register it first
: Try
: getbd("DTStamp","d")
: Else
: regbd("DTSTamp","d")
: EndTry
:
: ©Add date/time stamp if AMS clock is on
: If isClkOn() Then
: getDtStr()&" "&getTmStr()→#bfvar[bhin[4]]
: Else
: "Unknown"→#bfvar[bhin[4]]
: EndIf
:EndIf
:
:EndPrgm
In order to activate the hook, it is now necessary to register it into the bhooks variable (from a program or the Home Screen):
:setFold(ωbman3)
:openbd()
:If getType(bhooks)≠"LIST" Then
:newList(10)→bhooks:Fill "",bhooks
:EndIf
:"hdtstamp(2)"→bhooks[2]
:"hdtstamp(3)"→bhooks[3]
:closebd()
Now, whenever a backup is created or updated and the AMS clock is turned on, the current date and time will be recorded for that backup and stored in the backup database. This can be verified by checking the extended backup data of the View Properties dialog in Advanced Shell.
This example shows how to use a hook routine to implement custom error codes.
Hooks #9 and #10 are used to hook into the error-handling system. The goal is to hook the handler of unrecognized error conditions and define a new error code.
Suppose we already have a hook installed that generates error code 15000 when there is not enough memory to perform an operation. This error is triggered with this code:
15000→errornum:PassErr
This error code is not recognized by the errh routine, so it will simply return the message "Unknown error 15000--probably a bug." To allow the Backup Manager system to recognize the error, we write the following hook routine hnewerr:
:hnewerr(h)
:Prgm
:©Backup Manager 3 hook
:©Define a custom error code
:
:©Catch hook 10
:If h=10 Then
: ©Check for error #15000
: If bhin[1]=15000 Then
:
: ©Strip folder name from path, leaving just file name (there is not enough space in the error message for both)
: Local file,start
: inString(bhin[2],"\")→start
: when(start>0,mid(bhin[2],start+1),bhin[2])→file
: 15000→bhout
: "Not enough RAM to compress "&file→bhout2
: EndIf
:EndIf
:EndPrgm
Note that in our error message we include the name of the file where the error occurred, if available, but we strip off the folder name, leaving only the file name. Error text messages are limited to no more than 40 characters, so there is not enough room to show the entire path in this particular message. If a message of more than 40 characters is used, the error handler will crash with an AMS Dimension Error if it tries to display a dialog box for the error.
Now, we register the hnewerr hook (from a program or the Home Screen):
:setFold(ωbman3)
:openbd()
:If getType(bhooks)≠"LIST" Then
:newList(10)→bhooks:Fill "",bhooks
:EndIf
:"hnewerr(10)"→bhooks[10]
:closebd()
Now, when errh is called on an error, and errornum contains the value 15000, our custom error message will display.
One way to test this is by entering the following code on the Home Screen:
:setFold(ωbman3):openbd()
:Try:15000→errornum:PassErr
:Else:errh("foo\bar",true,false)
:EndTry
:closebd()
If all is well, a dialog should appear with the message "Not enough RAM to compress bar".