The On Exit Database Method is called once when you quit a database.
This method is used in the following 4D environments:
4D Client (on the client side)
4D application compiled and merged with 4D Runtime Volume License
Note: The On Exit Database Method is NOT invoked by 4D Server.
The On Exit Database Method is automatically invoked by 4D; unlike project methods, you cannot call this database method yourself. To call and perform tasks from within the On Exit Database Method, as well as from project methods, use subroutines.
A database can be exited if any of the following occur:
The user selects the menu command Quit from the User or Design Environment File menu
A call to the QUIT 4D command is issued
A 4D Plug-in issues a call to the QUIT 4D entry point
No matter how the exit from the database was initiated, 4D performs the following actions:
If there is no On Exit Database Method, 4D aborts each running process one by one, without distinction. If the user is performing data entry, the records will be cancelled and not saved.
If there is an On Exit Database Method, 4D starts executing this method within a newly created local process. You can therefore use this database method to inform other processes, via interprocess communication, that they must close (data entry) or stop executing. Note that 4D will eventually quitthe On Exit Database Method can perform all the cleanup or closing operations you want, but it cannot refuse the quit, and will at some point end.
The On Exit Database Method is the perfect place to:
Stop processes automatically started when the database was opened
Save (locally, on disk) Preferences or Settings to be reused at the beginning of the next session in the On Startup Database Method
Perform any other actions that you want to be done automatically each time a database is exited
Note: Don't forget that the On Exit Database Method is a local/client process, so it cannot access the data file. Thus, if the On Exit Database Method performs a query or a sort, a 4D Client that is about to quit will "freeze" and actually will not quit. If you need to access data when a client quits the application, create a new global process from within the On Exit Database Method, which will be able to access the data file. In this case, be sure that the new process will terminate correctly before the end of the On Exit Database Method execution (by using interprocess variables, by example).
The following example covers all the methods used in a database that tracks the significant events that occur during a working session and writes a description in a text document called "Journal."
The On Startup Database Method initializes the interprocess variable <>vbQuit4D, which tells all the use processes whether or not the database is being exited. It also creates the journal file, if it does not already exist.
` On Startup Database Method C_TEXT(<>vtIPMessage) C_BOOLEAN(<>vbQuit4D) <>vbQuit4D:=False If (Test path name("Journal") # Is a document) $vhDocRef:=Create document("Journal") If (OK=1) CLOSE DOCUMENT($vhDocRef) End if End if WRITE JOURNAL ("Opening Session")
The project method WRITE JOURNAL, used as subroutine by the other methods, writes the information it receives, in the journal file:
` WRITE JOURNAL Project Method ` WRITE JOURNAL ( Text ) ` WRITE JOURNAL ( Event description ) C_TEXT($1) C_TIME($vhDocRef) While (Semaphore("$Journal")) DELAY PROCESS(Current process;1) End while $vhDocRef:=Append document("Journal") If (OK=1) PROCESS PROPERTIES(Current process;$vsProcessName;$vlState;$vlElapsedTime;$vbVisible) SEND PACKET($vhDocRef;String(Current date)+Char(9)+String(Current time)+Char(9) +String(Current process)+Char(9)+$vsProcessName+Char(9)+$1+Char(13)) CLOSE DOCUMENT($vhDocRef) End if CLEAR SEMAPHORE("$Journal")
Note that the document is open and closed each time. Also note the use of a semaphore as "access protection" to the documentwe do not want two processes trying to access the journal file at the same time.
The M_ADD_RECORDS project method is executed when a menu item Add Record is chosen in Custom menus:
` M_ADD_RECORDS Project Method MENU BAR(1) Repeat ADD RECORD([Table1];*) If (OK=1) WRITE JOURNAL ("Adding record #"+String(Record number([Table1]))+" in Table1") End if Until ((OK=0) | <>vbQuit4D)
This method loops until the user cancels the last data entry or exits the database.
The input form for [Table 1] includes the treatment of the On Outside Call events. So, even if a process is in data entry, it can be exited smoothly, with the user either saving (or not saving) the current data entry:
` [Table1];"Input" Form Method Case of : (Form event=On Outside Call) If (<>vtIPMessage="QUIT") CONFIRM("Do you want to save the changes made to this record?") If (OK=1) ACCEPT Else CANCEL End if End if End case
The M_QUIT project method is executed when Quit is chosen from the File menu in the Custom Menus environment:
` M_QUIT Project Method $vlProcessID:=New process("DO_QUIT";32*1024;"$DO_QUIT")
The method uses a trick. When QUIT 4D is called, the command has an immediate effect. Therefore, the process from which the call is issued is in "stop mode" until the database is actually exited. Since this process can be one of the processes in which data entry occurs, the call to QUIT 4D is made in a local process that is started only for this purpose. Here is the DO_QUIT method:
` DO_QUIT Project Method CONFIRM("Are you sure you want to quit?") If (OK=1) WRITE JOURNAL ("Quitting Database") QUIT 4D ` QUIT 4D has an immediate effect, any line of code below will never be executed ` ... End if
Finally, here is the On Exit Database Method which tells all open user processes "It's time to get out of here!" It sets <>vbQuit4D to True and sends interprocess messages to the user processes that are performing data entry:
` On Exit Database Method <>vbQuit4D:=True Repeat $vbDone:=True For ($vlProcess;1;Count tasks) PROCESS PROPERTIES($vlProcess;$vsProcessName;$vlState;$vlElapsedTime;$vbVisible) If (((($vsProcessName="ML_@") | ($vsProcessName="M_@"))) & ($vlState>=0)) $vbDone:=False <>vtIPMessage:="QUIT" BRING TO FRONT($vlProcess) CALL PROCESS($vlProcess) $vhStart:=Current time Repeat DELAY PROCESS(Current process;60) Until ((Process state($vlProcess)<0) | ((Current time-$vhStart)>=?00:01:00?)) End if End for Until ($vbDone) WRITE JOURNAL ("Closing session")
Note: Processes that have names beginning with "ML_..." or "M_..." are started by menu commands for which the Start a New Process property has been selected. In this example, these are the processes started when the menu command Add record was chosen.
The test (Current time-$vhStart)>=?00:01:00? allows the database method to get out of the "waiting the other process" Repeat loop if the other process does not act immediately.
The following is a typical example of the Journal file produced by the database:
|2/6/03||15:47:25||1||User/Custom Menus process||Opening Session|
|2/6/03||15:55:43||5||ML_1||Adding record #23 in Table1|
|2/6/03||15:55:46||5||ML_1||Adding record #24 in Table1|
Note: The name $xx is the name of the local process started by 4D in order to execute the On Exit Database Method.
On Startup Database Method, QUIT 4D.