2. Communicating with the GemStone Object Server

Previous chapter

Next chapter

When you install GemBuilder, your Smalltalk image becomes “GemStone-enabled,” meaning that your image is equipped with additional classes and methods that allow it to work with shared, persistent objects through a multi-user GemStone object server. Your Smalltalk image remains a single-user application, however, until you connect to the object server. To do so, your application must log in to a GemStone object server in much the same way that you log in to a user account in order to work on a networked computer system.

This chapter explains how to communicate with the GemStone object server by initiating and managing GemStone sessions.

Client Libraries
explains how to setup to use the correct client shared libraries.

GemStone Sessions
introduces sessions and explains the difference between RPC and linked sessions.

Session Control in GemBuilder
explains how to use the classes GbsSession, GbsSessionManager, and GbsSessionParameters to manage GemBuilder sessions.

Logging In to and Logging Out of GemStone
describes how to log in and out of GemStone sessions programmatically.

Session Dependents
explains how to use the Smalltalk dependency mechanism to coordinate the effects of session management actions on multiple application components.

2.1  Client Libraries

Before you can log in to a GemStone object server, in addition to having GBS loaded in your image, you must have the client libraries available for loading into your image. The client libraries are provided with the GemStone object server product release. You must use the correct client libraries for the particular version of the object server you wish to connect to, and for the platform that the client Smalltalk image is running on. If you update to a new version of GBS, but continue to use the same version of the GemStone server, the same client libraries will be used.

There are a number of options for where to put your client libraries to they can be accessed by GBS, and options on how to set the library names in GBS. These options, as well as the correct client library name to use for your GemStone/S server product and version, are described in the GemBuilder for Smalltalk Installation Guide.

The current client library name is stored in the GbsConfiguration setting “libraryName”. This can be viewed or set using the Settings dialog, or you may execute:

GbsConfiguration current libraryName
GbsConfiguration current libraryName: ‘libraryName

For more information on this setting, see Chapter 10, “GemBuilder Configuration Parameters”.

2.2  GemStone Sessions

An application connects to the GemStone object server by logging in to the server and disconnects by logging out. Each logged-in connection is known as a session and is supported by one Gem process. The Gem reads objects from the repository, executes GemStone Smalltalk methods, and propagates changes from the application to the repository.

Each session presents a single-user view of a multiuser GemStone repository. Most applications use a single session per client; but an application can create multiple sessions from the same client, one of which is the current session at any given time. You can manage GemStone sessions either through your application code or through the GemStone Launcher.

RPC and Linked Sessions

A Gem can run as a separate operating system process and respond to Remote Procedure Calls (RPCs) from its client, in which case the session it supports is called an RPC session.

On platforms that host the GemStone object server and its runtime libraries, one Gem can be integrated with the application into a single operating system process. That Gem is called a linked session. When running linked, an application and its Gem must run on the same machine and the runtime code requires additional memory.

An RPC session offers more flexibility because the application and its Gem are separate processes that can run on different hosts in a network. Any GemBuilder client can create RPC sessions. Where a linked session is supported, an application can create multiple sessions, but only one can be linked. To suppress linked sessions, forcing all Gems to run as RPC processes, you can load the RPC-only version of the shared libraries.

Figure 2.1 shows an application with two logged-in sessions. Gem A is an RPC session running as a separate process, while Gem B is a linked session, sharing the client Smalltalk application's process space.

Figure 2.1   RPC and Linked Gem Processes
 

2.3  Session Control in GemBuilder

Managing GemStone sessions involves many of the same activities required to manage user sessions on a multi-user computer network. To manage GemStone sessions, you need to do various operations:

Three GemBuilder classes provide these session control capabilities: GbsSession, GbsSessionParameters, and GbsSessionManager.

GbsSession
An instance of GbsSession represents a GemStone session connection. A successful login returns a new instance of GbsSession. You can send messages to an active GbsSession to execute GemStone code, control GemStone transactions, compile GemStone methods, and access named server objects.

GbsSessionParameters
Instances of GbsSessionParameters store information needed to log in to GemStone. This information includes the Stone name, your user name, passwords, and the set of connectors to be connected at login.

GbsSessionManager
There is a single instance of GbsSessionManager, named GBSM. Its job is to manage all GbsSessions logged in from this client, support the notion of a current session (explained in the following section), and handle other miscellaneous GemBuilder matters. Whenever a new GbsSession is created, it is registered with GBSM. GBSM shuts down any server connections before the client Smalltalk quits.

Session Parameters

To initiate a GemStone session, you must first identify the object server and user account to which you wish to connect. This information is stored in an instance of GbsSessionParameters and added to a list maintained by GBSM. You can provide the information through window-based tools or programmatically. Both methods are described in later sections. In either case, you must supply these items:

  • The name of the GemStone repository
    For a Stone running on a host other than the Gem host (described below), you must include the server’s hostname in Network Resource String (NRS) format. NRS format is described in an appendix to the System Administration Guide. For instance, for a Stone named “gs64stone” on a host named “pelican”, specify an NRS string of the form:
!@pelican!gs64stone
  • GemStone user name and GemStone password
    This user name and password combination must already have been defined in GemStone by your GemStone data curator or system administrator. (GemBuilder provides a set of tools for managing user accounts—see User Account Management Tools.) Because GemStone comes equipped with a data curator account, we show the DataCurator user name in many of our examples.
  • Host username and Host password (not required for a linked session, or if netldi is run in guest mode)
    This user name and password combination specifies a valid login on the Gem’s host machine (the network node specified in the Gem service name, described below). Do not confuse these values with your GemStone username and password. You do not need to supply a host user name and host password if you are starting a linked Gem process. However, an application that must control more than one GemStone session can use a linked interface for only one session. Other sessions must use the RPC interface.
  • Gem service (not required for a linked session)
    The name of the Gem service on the host computer (that is, the Gem process to which your GemBuilder session will be connected). For most installations, the Gem service name is gemnetobject.

You can specify that the gem is to run on a remote host by using an NRS for the Gem service name For example:

!@pelican!gemnetobject

You do not need to supply a Gem Service name if you are starting a linked Gem process.

Once defined, an instance of GbsSessionParameters can be used for more than one session. Thus, a session description that includes the RPC-required parameters can be used for both linked and RPC logins.

Defining Session Parameters Programmatically

The instance creation method for a full set of RPC parameters is:

GbsSessionParameters newWithGemStoneName: aGemStoneName
username: aUsername
password: aPassword
hostUsername: aHostUsername
hostPassword: aHostPassword
gemService: aGemServiceName

For a shorter set of parameters that supports only linked logins, you can use a shorter creation method:

GbsSessionParameters newWithGemStoneName: aGemStoneName
username: aUsername
password: aPassword
Storing Session Parameters for Later Use

If you want the GemBuilder session manager to retain a copy of your newly-created session description for future use, you must register it with GBSM:

GBSM addParameters: aGbsSessionParameters

Once registered with GBSM and saved with the image, the parameters are available for use in future invocations of the image. In addition, the GemStone Launcher and other login prompters make use of GBSM’s list of session parameters.

Executing the expression GBSM knownParameters returns an array of all GbsSessionParameters instances registered with GBSM.

To delete a registered session parameters object, send removeParameters: to GBSM:

GBSM removeParameters: aGbsSessionParameters
Password Security

You can control the degree of security that GemBuilder applies to the passwords in a session parameters object. For example, when you create the parameters object, you can specify the passwords as empty strings. When the parameters object is subsequently used in a login message, GemBuilder will prompt the user for the passwords.

For example:

mySessionParameters := GbsSessionParameters
newWithGemStoneName: '!@pelican!gs64stone'
username:            'DataCurator'
password:            ''
hostUsername:        'lisam'
hostPassword:        ''
gemService:          '!@pelican!gemnetobject'

If convenience is more important than security, you can fill in the passwords and then instruct the parameters object to retain the password information for future use:

mySessionParameters rememberPassword: true;
rememberHostPassword: true

The default “remember” setting for both passwords is false, which causes the stored passwords to be erased after login.

2.4  Logging In to and Logging Out of GemStone

Before you can start a GemStone session, you need to have a Stone process and, for an RPC session, a NetLDI (network long distance information) process running.

Depending on the terms of your GemStone license, you can have many sessions logged in at once from the same GemBuilder client. These sessions can all be attached to the same GemStone repository, or they can be attached to different repositories.

Logging In to GemStone

The protocol for logging in is understood both by GBSM and by instances of GbsSessionParameters. To log in using a specific session parameters object, send a login message to the parameters object itself:

mySession := aGbsSessionParameters login

To start multiple sessions with the same parameters, simply repeat these login messages.

An application can also send a generic login message to GBSM:

mySession := GBSM login

This message invokes an interactive utility that allows you to select among known GbsSessionParameters or to create a new session parameters object using the Session Parameters Editor.

A successful login returns a unique instance of GbsSession. (An unsuccessful login attempt returns nil.) Each instance of GbsSession maintains a reference to that session’s parameters, which you can retrieve by sending:

myGbsSessionParameters := aGbsSession parameters

GBSM maintains a collection of currently logged in GbsSessions. You can determine if any sessions are logged in with GBSM isLoggedIn and you can execute GBSM loggedInSessions to return an array of currently logged in GbsSessions.

The Current Session

When a new GbsSession is created, it is registered with GBSM, which maintains a variable that represents the current session. When a session logs in, it becomes the current session. If you execute code in a GemStone tool, the code is evaluated in the current session, or in the session that was current when you opened that tool. If you send a message to GBSM that is intended for a session, the message is forwarded to the current session.

You can send a message directly to any logged-in GbsSession, even when it is not the current session. If you send a specific session a message that executes code, that code is evaluated in the receiving session, regardless of whether it is the current session.

Most applications have only one session logged in at a time. In this case, that session will always be the current session, and it is safe to send messages to GBSM for forwarding to the session.

However, if your application concurrently logs in more than one session, your application should send messages directly to each session. If your application client uses multiple Smalltalk processes it is very difficult to accurately coordinate the changing of the current session.

Sending the message GBSM currentSession returns the current GbsSession. You can change the current session in a workspace by executing an expression of the following form:

GBSM currentSession: aGbsSession.

Your application can make another session the current session by executing code like that shown in Example 2.1:

Example 2.1 
|s1 s2|
s1 := GBSM login.
s2 := GBSM login.
GBSM currentSession: s1.  "Make s1 current" 
. 
.	"Do some work" 
.
GBSM currentSession: s2.  Make s2 current" 
 

Each GemStone browser, inspector, debugger, and breakpoint browser is attached to the instance of GbsSession that was the current session when it opened. For example, you can have two browsers open in two different sessions, such that operations performed in each browser are applied only to the session to which that browser is attached.

Workspaces, however, are not session-specific. Executing a GS-Do it in a workspace will execute in the current session.

Logging Out of GemStone

To instruct a session to log itself out, send logout to the session object:

aGbsSession logout

Or, you can execute the more generic instruction:

GBSM logout

This message prompts you with a list of currently logged-in sessions from which to choose.

Before logging out, GemBuilder prompts you to commit your changes, if the GbsConfiguration setting confirm is true (it is true by default). If you log out after performing work and do not commit it to the permanent repository, the uncommitted work you have done will be lost.

If you have been working in several sessions, be sure to commit only those sessions whose changes you wish to save.

2.5  Session Dependents

An application can create several related components during a single GemBuilder session. When one of the components commits, aborts, or logs out, the other components can be affected and so may need to coordinate their responses with each other. In the GemBuilder development environment, for example, you can commit by clicking on a button in the GemStone Launcher. But before the commit takes place, all other session-dependent components are notified that a commit is about to occur. So a related application component, such as an open browser containing modified text, prompts you for permission to discard its changes before allowing the commit to proceed.

Through the Smalltalk dependency mechanism, any object can be registered as a dependent of a session. In practice, a session dependent is often a user-visible application component, such as a browser or a workspace. When one application component asks to abort, commit, or log out, the session asks all of its registered dependents to approve before it performs the operation. If any registered dependent vetos the operation, the operation is not performed and the method (commitTransaction, abortTransaction, etc.) returns nil.

To make an object a dependent of a GbsSession, send:

mySession addDependent: myObj

To remove an object from the list of dependents, send the following message:

mySession removeDependent: myObj

So, for example, a browser object might include code similar to Example 2.2 in its initialization method:

Example 2.2 
| mySession |
mySession := self session.
"Add this browser to the sessions dependents list"
(session dependents includes: self)
	ifFalse: [session addDependent: self]
...
 

When a session receives a commit, abort, or logout request, it sends an updateRequest: message to each of its dependents, with an argument describing the nature of the request. Each registered object should be prepared to receive the updateRequest: message with any one of the following aspect symbols as its argument:

#queryCommit
The session with which this object is registered has received a request to commit. Return true to allow the commit to take place or false to prevent it.

#queryAbort
The session with which this object is registered has received a request to abort. Return true to allow the abort to take place or false to prevent it.

#queryEndSession
The session with which this object is registered has received a request to terminate the session. Return true to allow the logout to take place or false to prevent it.

Example 2.3 shows how a session dependent might implement an updateRequest: method.

Example 2.3 
updateRequest: aspect
 
"The session I am attached to wants to do something.
Return a boolean granting or denying the request."
 
^(#(queryAbort queryCommit queryEndSession)
	includes: aspect)
		ifTrue: [ self askUserForPermission ]
		ifFalse: ["Let any other action occur." 
					true]
 

After the action is performed, the session sends self changed: with a parameter indicating the type of action performed. This causes the session to send an update: message to each of the registered dependents with one of the following aspect symbols:

#committed
All registered objects have approved the request to commit, and the transaction has been successfully committed.

#aborted
All registered objects have approved the request to abort, and the transaction has been aborted.

#sessionTerminated
The request to log out has been approved and the session has logged out.

Each registered dependent should be prepared to receive an update: message with one of the above aspect symbols as its argument. Example 2.4 shows how a session dependent might implement an update: method.

Example 2.4 
update: aSymbol
"The session I am attached to just did something.
I might need to respond."
 
(aSymbol = #sessionTerminated) ifTrue: [
"The session this tool is attached to has logged out
  - close ourself."
self builder notNil ifTrue:
	[self closeWindow]]
 

Figure 2.2 summarizes the sequence of events that occurs when a session queries a dependent before committing. In the figure, the GemStone Launcher sends a commit request (commitTransaction) to a session (1). The session sends updateRequest: #queryCommit to each of its dependents (2). If every dependent approves (returns true), the commit proceeds (4). Following a successful commit, the session notifies its dependents that the action has occurred by sending update: #committed to each (5).

 

Figure 2.2   Committing with Approval From a Session Dependent
 

Previous chapter

Next chapter