FileMaker Pro is a client/server application (at least when files are being hosted by an individual user or by FileMaker Server). Each time someone using FileMaker Pro (a client) connects to FileMaker Server and opens an instance of the files hosted there, he creates a session.
In practical terms, this means that one of your users can be on layout #10 while you yourself are working with layout #2. You can run a script and nothing will necessarily happen on another user's computer; likewise, someone else can export data on her machine, while you're performing a find request in the very same database table on yours. You each have a separate connection to the database, with its own unique environment. While working with the same data, all your users can be performing separate, distinct tasks in your system. Each user can have a separate view of the database, with different active windows, active tables, or active found sets, among other things.
Generally, these individual user sessions don't interfere with each other at all; however, there are cases in which they can conflictfor example, when two users try to edit the same record at the same time. We will cover throughout this chapter various techniques for identifying and coping with such issues.
The one thing that is consistent across all user sessions is the actual data in the database. Changes you make to records you are editing are immediately visible to other users in the system, and vice versa. Our discussion of sessions pertains only to global fields and variables, window states, and layouts. Actual data is stored and displayed consistently for everyone.
Before approaching how to manage sessions and potential conflicts, it is important to understand what a session is and how FileMaker Pro manages multiple users. In FileMaker Pro, sessions are implicit and enjoy a stateful, persistent, always-on connection to the server. The system preserves and isolates each user experience in the FileMaker Pro client. Keep in mind that after the session is over (an individual user closes the database), all information about that sessionwhat layout was in use, where windows were positioned, what the found set wasis discarded. The next time that user opens the database in question, it opens in its default state, with no preservation of how the user last left the system.
You might have heard the term session as applied to the Web. FileMaker Pro is quite different. On the Web, connections are stateless by defaultthey have no memory. The web server does not maintain a connection to a user; the effect of a persistent session is approximated by the explicit creation of an identifier for a given user when she logs in to a system. That identifier is then passed (and often stored/retrieved via a cookie) through all the page requests a person may make in a given time period. Web developers need to explicitly create the mechanics of a session to preserve a user's experience from page to page. Whenever you buy a book from Amazon, the developers there have no doubt labored to make sure that each page you visit tracks sensibly your use of the siteespecially when it comes to the multipage shopping cart experience. FileMaker, by contrast, provides persistent database sessions with no additional effort by you, the developer.
FileMaker Pro's sessions maintain a consistent user experience until the application itself is closed. This experience includes your login account (unless you specifically log out and log back in), the position and number of windows you have open, which layouts you're on, your current found set, your current sort order, and portal scroll positions. On the development side of things, custom colors you've stored in the layout tools are, unfortunately, lost at the end of a session as well.
Globals (fields specified as having global storage, as well as global script variables) are session-specific and require additional discussion. In a multiuser client session, they utilize and hold values unique to one specific user's session. This enables you as a developer to depend on globals storing different information for each user. A simple example is a displayed account name at the top of each layout set at the time of login.
For more details on global field storage, see "Storage and Indexing," p. 86.
At the start of a session, each global field is initialized to the last value it had in single-user mode. If you run in single-user mode only, this makes the global field value appear to persist across sessions, but it's misleading to infer that there are multiuser and single-user types of sessions. Storing information in global fields for single users is a handy way to leave things the way they were, but it also allows developers to create a default state for global fields.
Global fields are used for a range of functions in multiuser databases: They often hold images for navigation and user interface purposes and they sometimes hold session information such as the current date or the active, logged-in user. It makes sense, then, that they'd be specific to a given user's experience.
If your global fields suddenly seem to be holding wrong data, refer to "Unpredictable Global Default Values" in the "Troubleshooting" section at the end of this chapter.
Global variables, on the other hand, do not have stored values from session to session in single or multiuser mode. As a developer you will need to explicitly initialize the variables you intend to have the system utilize, ideally at the beginning of each session.
For a complete discussion of script variables, see "Script Variables," p. 448.
User Accounts and Session Data
One common use of global behavior in a multiuser environment is to set a global field with your currently logged-in account. This enables you to always have a central stored value that's easy to use in calculation formulas and scripts. One could argue that simply using the Get (AccountName) function wherever necessary would accomplish the same end, but there's an additional use for storing the current account name in a global: You can drive a relationship with it into a User table by using the account name as a unique match field.
Note that a global variable, as opposed to a global field, cannot drive a relationship. This difference can play a significant role in determining whether to store particular session data in a global field or a global variable.
This enables you to tie account information to data. You might want to do this if, for example, you need to store someone's real name, her preference to always start on a specific layout when the system opens, or (in a particularly abstract example) in what language she wants to use your database.
All these examples depend on your having done something with the information you store in a user table. It's useful to store someone's preference for a starting layout only if you then write the requisite script that uses this as a reference.
Another possibility lies with tracking database use. Although you might debate whether a database (or database administrator) should be looking over someone's shoulder, you could write routines that post records to a user log table whenever users log in, log out, or even when they perform certain scripted actions (delete records, create records, run an invoice report, and so on).
One more user-friendly option is to accommodate users simply by enabling them to specify where they prefer a window to be positioned and sized. All these various options can be enabled by storing information specific to a single person's session in global fields.