ODB name:suites.session
Version:1.0b3
Version Date:1998/11/04
Compatibility: F5.0.1 - F5.0.2b - F5.1+ - F6.0
Download: Fatpage
Release notes

The Session Support Suite

By Samuel Reynolds, reynol@primenet.com.

While working on a web application, I found that I needed to store far more information about a user session than would fit in an HTTP cookie. So I wrote the Session suite to provide a mechanism to track arbitrary amounts of session information, and to automatically delete such information after a period of time if the session is not explicitly terminated.

The session suite helps you manage session-specific data: getting a unique session identifier, repeatedly accessing a session data table, expiring a session through timeouts, and deleting/cleaning up session data after completion.

The session suite is designed with web-based applications such as "shopping carts" in mind. (Also for gaming aids such as complex vehicle design programs, but that's of less general interest.) It provides a mechanism for sharing arbitrarily large amounts of information across multiple invocations of a CGI or dynamic web page by providing a session identifier that can be embedded in the web page (as a cookie or a hidden field in a form) and managing a table of data associated with that identifier.


Copyright and Permissions

Copyright © 1998 by Samuel Reynolds. All rights reserved.

Permission is hereby granted to use the scripts in this suite for private or commercial use at no charge, and to distribute them with this documentation in their original form. You may modify the scripts for such purposes, but may not distribute the modified versions of the scripts without the author's permission (readily granted).

If you have suggestions or changes you think should be included for distribution with future versions of this software, please contact the author at .


Installation and Configuration

To install the session support suite, run the script at session.Init. This script creates and initializes the user.session table (if necessary), and installs the sessionAgent script in system.agents. In older versions if Frontier that have a table system.verbs.builtins.semaphores instead of system.verbs.builtins.semaphore, it creates the latter as a copy of the former. (The name was changed in Frontier 5.1.)

The session agent script runs at an interval defined by user.session.cleanupInterval. This cleanup interval may be changed at any time; it is read anew each time the agent runs.

To de-install the session support suite, run the script at session.Uninstall. This script deletes all the items installed by session.Init (except system.verbs.builtins.semaphore, even if it was created by session.Init). Deleting the suite from the ODB will complete the de-installation.


How It Works

When session.NewSession() is called, a session tracking table is created inside the table user.session.sessions. A unique session ID string is generated, used as the name of this tracking table, and is returned to the caller.

Remember the session ID: it's your key to session-support services.

The session tracking table records the expireInterval and expected expiration time (date and time, actually) of the session. The tracking table also contain a subtable for use by the session creator for storing data between session activities. This subtable is the session data table.

To use the session data table, call session.SessionData(), passing the session ID. SessionData() restarts the session expiration (interval) timer before returning the address of the session data table.

Use the session data table to store application information that must be maintained between successive web application submissions (CGI calls), but which you do not want to (or cannot) include in successive HTML forms as cookies or hidden fields. To maintain session continuity, place the session ID in a hidden field or cookie. Then a simple call to session.SessionData() will retrieve the associated data.

Just prior to returning a CGI result to the browser, or while computing your return text if such computation takes a long time, call session.KeepAlive() to restart the session expiration timer. That way your users' session intervals are not artificially shortened by your application's processing time.

When your application session is complete, a call to session.Terminate() will terminate the session immediately. If you fail to call session.Terminate(), the session will remain active until the session expiration timer times out. This could confuse your application.

The session support suite uses semaphores internally to manage shared access to the user.session table. The semaphore name is always the address of the session tracking table as a string.


The Session Agent Script

The session agent script (system.agent.sessionAgent) periodically scans the user.session.sessions table and deletes the tracking tables of sessions whose expiration (interval) timers have timed out. Since the session data table is contained in the session tracking table, this deletes all session data, as well.

The session agent script runs at an interval defined by user.session.cleanupInterval. This cleanup interval may be changed at any time; it is read anew each time the agent runs.

Because the agent runs at fixed intervals, any given session may not be deleted after exactly its expiration interval; it will not be deleted until the next run of the agent after its expiration interval is exceeded. Since session expiration intervals are anticipated to be in the 10-minute to 1-hour range, this "slop" should not be harmful. If you need the session to be killed as soon as possible after the expiration interval, set the cleanup interval (user.session.cleanupInterval) to 1 second (the smallest it can be).


The Session Support Scripts

NewSession( expireInterval, prefix, busyCallback, cleanupCallback )

expireInterval: If this interval elapses before any new activity occurs in the session, the session expires and is deleted. New activity constists of calls to session.SessionData() or session.KeepAlive().

prefix: The prefix to be used in creating a session ID string. This is provided to make debugging easier; if you never provide a prefix, the session suite will never notice. [OPTIONAL] Defaults to "S".

busyCallback: The address of a function to call whenever the session expiration timer is reset. This provides a mechanism for periodic operations and monitoring. See Callback Functions, below, for more information. [OPTIONAL] Defaults to nil.

cleanupCallback: The address of a function to call when the session terminates. This provides a mechanism for application-specific termination. See Callback Functions, below, for more information. [OPTIONAL] Defaults to nil.

Create a new session tracking table, assign a session ID, and return the session ID to the caller. Remember the session ID: it's your key to session-support services.

Terminate( sessionId )

sessionId: The unique session identifier created by a call to NewSession().

Immediately terminate the specified session and delete the session's tracking table. The session data table is unavailable after Terminate() is called.

SessionData( sessionId )

sessionId: The unique session identifier created by a call to NewSession().

Return the address of the session data table for the specified session. Also restarts the session expiration (interval) timer.

KeepAlive( sessionId )

sessionId: The unique session identifier created by a call to NewSession().

Restart the session expiration (interval) timer.

KeepAliveNoLock( oneSessionTbl )

Restart the session expiration (interval) timer. Do not wrap the operation in a semaphore lock/unlock. Provided for use by callback functions only. See Callback Functions, below, for more information.


Callback Functions

When you call NewSession to create and initialize a session, you can provide the address of two different functions to be called when certain session events occur.

When the appropriate event occurs, the corresponding function (if provided) will be called with the address of the session tracking table and the address of the session data table. Do not attempt to modify the session tracking table. You can do what you wish within the session data table; the session suite never looks inside that table. You may also get the session ID by calling nameOf(sessionTrackingTbl^). The session tracking table address is provided so that you can pass it in calls to session.utils.KeepAliveNoLock if your callback function takes a significant amount of time to complete.

The callback functions are called from within the context of a locked semaphore. Therefore, you must not call the following routines from within your callback functions:

KeepAlive
SessionData
Terminate
Calling any of these routines from within your callback function will lock up your application.

If your callback function is performing operations that may take longer than your session expiration interval, you may call session.utils.KeepAliveNoLock from within your callback function to reset the session expiration timer.

The events for which you can install callback functions are:

Busy:

The session expiration timer is being reset.

The callback function may perform periodic tasks such as monitoring your application.

The callback function's return value is ignored.

Cleanup:

The session has expired and the session tracking table is about to be deleted.

The callback function should perform any cleanup required by your application prior to session termination. Since the entire table is about to be deleted, you do not need to delete entries from the session data table. Because the termination process has already begun as a result of session expiration, you cannot extend the session by calling session.utils.KeepAliveNoLock; the session expiration timer is ignored at this point.

The callback function's return value is ignored.


Tips and Warnings

If you use the session support suite with a multithreaded app, and share the session data table between multiple threads, use a string containing the session ID as the name of a semaphore to avoid race conditions and probable crashes.

If you use callback functions, do not use the address of the session tracking table as the name of a semaphore.

If you need extra time within a callback function, don't call KeepAlive; call utils.KeepAliveNoLock instead. See the section on Callback Functions, above, for more information.


Release Notes


This page is a Fat Page. It includes the above script(s), encoded by and for Frontier. To retrieve the script(s), save the page as source text and open it using the File->Open command.

Copyright © 1998, 1999 by Samuel Reynolds. All rights reserved. Last modified 1999/08/03.
Built with Frontier v.6.0 on Macintosh OS 8.1 on 1999/08/03.