*-----Sessions---------------------------------by Charles Overbeck- Charles Overbeck is a key member of the Visual dBASE development team. Though, with all due modesty, he will disclaim full responsibility (some parts apparently existed before he got his hands into it), Charles is the guiding force behind the new Visual dBASE 6.0 Report Class. We suspect that, once VdB programmers get -their- hands on it, Charles is going to be a very popular guy. The following article is on Sessions - one of the most elusive yet powerful features of Visual dBASE. Sessions were designed to be so automatic that many of us have a hard time getting control of them within our applications. Charles' lucid explantion of CREATE SESSION should shed some light on the most misunderstood Visual dBASE command. Sessions in Visual dBASE Sessions are a very important and powerful part of Visual dBASE. With sessions, you can easily have multiple instances of the same form, each instance of the form positioned on a different record and not affecting the data displayed on other instances of the form. In effect, you can simulate several users on a network on just one machine. But based on message traffic on CompuServe and the Usenet, it appears that sessions remain somewhat of a mystery to many users. This article will attempt to clarify how sessions work and how they should be used, setting you on your way to exploiting their full power. What is a session?... A session is an object that consists of 1) a set of workareas; 2) the values of most SET commands. Each session's "environment" is completely independent of the environment of other sessions. For example, if you are in session #2, and you move the record pointer to record #5 in Customer.dbf, it will have no effect on the Customer.dbf record pointer in session #1. As another example, if SET TALK OFF in session #3, it has absolutely no effect on the value of TALK in session #1. It helps to think of a session as a different user on a network. If lock a table's record in one session, you can't lock that record in any other session until the first session unlocks it. The Visual dBASE Online Help provides a list of exactly which SET commands are stored for each session under the "CREATE SESSION" topic. Why use Sessions? Sessions encapsulate your forms. They make each form independent of all others, making it easy to have multiple instances of the same form class. You can have different forms accessing the same table, with each form positioned on a different record. In general, record navigation in one form does not affect record navigation in other forms. How is a session created? When Visual dBASE is loaded, you are automatically in a session. This is a special session--we'll call it the "Startup Session". It is important because new sessions created by the user derive their default environment from the Startup Session (more on this below). You can generate a new session for Forms and reports by issuing the CREATE SESSION command, or by turning on the Desktop Properties Sessions Checkox. What exactly does the Sessions checkbox in the Desktop Properties dialog do? The Sessions checkbox is a visual representation of the Sessions entry in the Dbasewin.ini. If the value of the Sessions entry in the INI file is not 0, then forms and BROWSEs launched via Visual dBASE's UI will have a CREATE SESSION command "piped out" (commands automatically sent to the Command Window - ed.) before the form, BROWSE or report is launched. If Sessions is 0, then the CREATE SESSION is not piped out to the Command Window. Example: With Sessions checkbox on. * Double-click on a form, e.g., animals.wfm, in the Navigator. * The following code will be piped out and executed in the Command window: CREATE SESSION DO C:\VISUALDB\SAMPLES\ANIMALS.WFM * Now select File | Open, and select ANIMALS.DBF. * The following code will be piped out and executed in the Command window: CREATE SESSION USE D:\VISUALDB\SAMPLES\ANIMALS.DBF BROWSE If the Sessions checkbox is off, then for both cases above, the CREATE SESSIONs are not piped out, but the other lines are. Because the Sessions checkbox only affects forms and BROWSE's launched via the UI, this means that the setting of the Sessions checkbox is absolutely irrelevant forms or reports launched from within a program. When you launch a form from your application, it will appear in a new session only if you have explicitly issued a CREATE SESSION earlier in your code. For reports however, Sessions does have an effect even if you launch the report from within a program. If the Sessions setting in the INI is not "0", The Report Form command launches your report in a new session. Otherwise the report runs in the current session. If you want reports in your compiled programs to start in their own sessions, you could set the Sessions entry of your application's INI file. For example, if your Visual dBASE compiled app is called MYAPP.EXE, then add the following lines to MYAPP.INI (creating MYAPP.INI if necessary): [Settings] Sessions=1 If you don't want Visual dBASE to create a new session each time a report is launched, use the following in MYAPP.INI: [Settings] Sessions=0 What happens when a new session is created?... 1) A new set of empty workareas is created and available. 2) The SET values are initialized to the values of the Startup Session as they were when Visual dBASE was initially loaded. Note that this is not necessarily the same as the current values of SET. For example, assume that TALK defaults to ON when you load Visual dBASE (which it does). Then: *Load Visual dBASE * From the Command window ? set('talk') && returns ON set talk off && Startup Session's value of talk is now OFF create session ? set('talk') && returns ON--the a copy of the initial value of the Startup Session Reference Counters... Sessions are "reference-counted". When the Create Session command is issued, the newly created session has a reference count of 0 (there's no forms, browses or reports that can "reference" that session). Each time you open a form, launch a report or issue the BROWSE command (note we're referring to the command, not the Browse Class - ed.), a counter in the session is incremented by 1. When forms are released, reports completed or Browses closed, the session's reference counter is decreemented by 1. In essence, the Session keeps track of how many "objects" were "created" in that session. When is a session released?... A session is released when a "session switch" occurs and the reference count of the current session is 0. Example: * From the Comand window create session && New session has reference count of 0 f = new form() f.open() && form references the new session, so new session has && reference count of 1 f.release() && session's reference count is decremented to 0. * A "session switch" occurs here, releasing the session. The Startup Session is never released while Visual dBASE is running; it is only released when you quit. What is a "session switch"?... A "session switch" is simply when you go from one session to another. They are important to understand, because it is when a "session switch" occurs that the reference count of the current session is evaluated--and if the reference count of the current session is 0, that session is released. When does a session switch occur?... There are 3 ways a session switch can occur: 1) The Create Session command. This command creates a new session and makes the new session the current session. Since you are in a new session, a switch has occured. 2) Activating a form/window. Since forms reference sessions, it makes sense that when a form has focus, the form's session should be the active session. Thus if you are on Form1 that references Session1 and click on Form2 that references Session2, a session switch will occur, and Session2 will become the current session. Note that clicking again on the currently active form/window does not cause a session switch to occur. Sessions switch only when focus changes from one form to another. 3) Executing the method/event of a form. Since the method of a form may access tables that are in the session referenced by the form, that session must be the current session when you execute any method of the form. Upon completion of the method, the previous current session is restored. So, actually, two session switches may occur when you execute the method of a form--one when you invoke the method, and another when the method is finishes executing. What happens when a session released? All tables open in the session are closed. You do not need to explicitly close those tables if you choose not to--they will be closed for you. A simple example: * From the Command window create session f = new form() f.view = 'animals.dbf' f.open() && After the open, you are back in the Command window and && in the Startup Session use animals exclusive && Fails, because Animals is open in && another session. f.close() use animals exclusive && Still fails, because the session && and its table are still open f.release() && Session referencing f will be released. use animals exclusuve && Works, because Animals was automatically && closed when the other session was released Debugging Sessions... I find that a simple tool to use in debugging sessions is the Navigator. Although the Navigator references the Startup Session (see below), the Navigator does show whether tables are open (in any session or sessions) or closed. If a table is open, then its name is italicized. For example: * From the Command window, no tables are open. create session use animals && note how animals becomes italicized in the Navigator use && Animals is no longer italicized in the Navigator use animals && animals is italicized again browse && animals is still italicized, even if you switch && to another window. * Close the Browse window * Note that Animals is no longer italicized. That means when you closed the Browse, the session referenced by the Browse was released, and Animals was closed. The Navigator and Command windows... The Navigator and Command windows reference the Startup Session. When you click on either of those windows from another window, a session switch occurs and the Startup Session becomes the current session. Even though you may type Create Session in the Command window, that new session is not referenced by the Command window. Commands that you type in will still be against the Startup Session. The above explains the following behaviour: * In the Command window, in the Startup Session create session && creates a new session (call it Session1), && with a reference count of 0 use animals && open a table * Click on the Navigator * A session switch occurs here: * Navigator is activated, Startup Session is activated. * Reference count of Session1 is evaluated -- it is 0, so it's released, and Animals is closed. * Click on the Command Window * As you can see, Animals is no longer open. Reports and sessions... Reports can be different than forms in that a session may automatically be created for the report. If the Sessions entry in Dbasewin.ini (or the INI file whose name matches the name of your Visual dBASE compiled EXE) is 1, then when you launch a report with the REPORT FORM command, the tables for the report will be opened in a new session. A Bug... The current release of Visual dBASE (5.5a) has a problem when you call the Release() method of a form while you are executing that form's ReadModal(). The Release() will not do anything (not even close the form). If you find a session is still open when you don't expect it to be, this might be the problem. To ensure that the session is closed (and the form really released), call the Release() method of the form while you are not in the ReadModal(). Ex: create session f = new form() p = new pushbutton(f) p.onclick = {;form.release()} f.readmodal() && Click on the pushbutton--nothing happens. * Close the form f.release() && form and session will now go away. Note that there is no problem if you had called the form's Open() method instead of its ReadModal() method. Some Examples * Examples are typed in interactively in the Command window. 1) create session create session create session create session How many new sessions exist after typing the above 4 commands? Answer: one (1). Remember, each Create Session causes a session switch. And since each newly created session has a reference count of 0, that means each Create Session releases the previous session (except for the Startup Session, which is never released). 2) create session f = new form f.view = 'animals.dbf' p = new pushbutton(f) p.onclick = {;f2 = new form(); f.open()} f.open() * Click on pushbutton. * Two forms are now using the same session. * Close the first form. Because another form references the session, the session is not closed and animals.dbf remains open. * Close the second form. No more references exist to the session, so it is released, and animals.dbf is closed. Ed. Note: If you're new to Visual dBASE, you may not be aware that the Query Generator issues a "Close Databases/Create Session". If you find yourself lost in an unexpected session, this may well prove to be the culprit. Remove Create Sessions from your .QBE's unless you -really- want the session created each time a form opens using that query as a View.