This chapter describes the overall design of a GemBuilder application and presents the fundamental concepts required to understand the interface between client Smalltalk and the GemStone object server.
The GemStone Object Server
introduces GemStone and its architecture and explains the part each component plays in the system.
GemBuilder for Smalltalk
outlines the basic features of GemBuilder that allow you to access GemStone objects from your Smalltalk application, and describes the basic programming functions that GemBuilder provides.
Designing a GemStone Application: an Overview
outlines the basic steps involved in producing a client/server application with GemBuilder.
The GemStone object server supports multiple concurrent users of a large repository of objects. GemStone provides efficient storage and retrieval of large sets of objects, resiliency to hardware and software failures, protection for object integrity, and a rich set of security mechanisms.
The GemStone object server consists of three main components: a repository for storing persistent, shared objects; a monitor process called the Stone, and one or more user processes, called Gems.
Figure 1.1 shows how the object server supports clients in a Smalltalk application environment.
The object repository is a multiuser, disk-based Smalltalk image containing shared application objects and GemStone kernel classes. It is composed of files (known to GemStone as extents) that can reside on a single machine or can be distributed among several networked hosts. The repository can also include GemConnect objects representing data stored in third-party relational databases.
Your Smalltalk application program treats the repository as a single unit, regardless of where its elements physically reside.
A Gem is an executable process that your application creates when it begins a GemStone session. A Gem acts as an object server for one session, providing a single-user view of the multiuser GemStone repository. A Gem reads objects from the repository, executes GemStone Smalltalk methods, and updates the repository.
Each Gem represents a single session. An application can create more than one session, each representing an internally-consistent single view of the repository. When a Gem commits a transaction, it modifies the shared repository and updates its own view of the repository.
The Stone monitor process handles locking and controls concurrent access to objects in the repository, ensuring integrity of the stored objects. Each repository is monitored by a single Stone.
Despite its central role in coordinating the work of all individual Gems, the Stone is surprisingly unintrusive. To optimize throughput for all users, most processing is handled by the Gems, which often interact directly with the repository. The Stone intervenes only when required to ensure the integrity of the multiuser repository.
GemBuilder for Smalltalk is a set of classes and primitives that can be installed in a client Smalltalk image. With the functionality provided by GemBuilder, you can:
Your client Smalltalk application creates a GemStone session by using GemBuilder to log in to GemStone, creating one or more Gem process to serve your application.
As Figure 1.1 illustrates, several applications can work concurrently with a single repository, with each application viewing the repository as its own. GemStone coordinates transactions between each of the applications and the repository.
The interface between your client Smalltalk application and GemStone can be relatively seamless.
Many of the classes in the base client Smalltalk image are mapped to comparable GemStone server classes, and additional class mappings can be created either automatically or explicitly. GemBuilder is also able to automatically generate GemStone server classes from client classes, and vice versa, as necessary. Your client objects can be replicated in the GemStone server, and GemStone server objects can be replicated in client Smalltalk.
Only server objects can become persistent in the GemStone object repository. To make a client Smalltalk object persistent, it must be mapped to a server object. This mapping is a relationship between a client object and a server object, whereby each represents the other. Once objects are mapped, GemBuilder maintains the relationship between the shared GemStone server object and the private client Smalltalk object, updating values from the repository to your application and vice versa, as necessary, as well as forwarding messages between the objects. Chapter 3 describes the replication of state and forwarding of messages between client and server objects.
Your client Smalltalk application updates shared objects in the repository by sending a commitTransaction message to a session. With a successful commit, changes to objects in the current session are propagated to the shared object repository in GemStone. Once you have committed a transaction, your application objects are updated with the most recently saved state of the repository, incorporating changes made by other users.
While, for the most part, GemBuilder will automatically manage objects in both the client Smalltalk and in the GemStone server, you can exert as much control as you want over how objects are stored and used. GemBuilder provides tools that let you specify customized policies for translating between your client Smalltalk and GemStone server objects.
GemStone provides a version of Smalltalk that supports multiple concurrent users of the shared object repository through such features as session management, reduced-conflict collection classes, querying, transaction management, and persistence.
GemStone Smalltalk is like single-user client Smalltalk in both its organization and syntax. Objects are defined by classes based on common structure and protocol and classes are organized into an is-a hierarchy, rooted at class Object. The class hierarchy is extensible; new classes can be added as required to model an application. The behavior of common classes conforms to the ANSI standard for Smalltalk. GemStone’s class hierarchy is discussed in the GemStone Programming Guide.
The most significant difference between GemStone Smalltalk and client Smalltalk lies in GemStone’s support for a multiuser environment in which persistent objects can be shared among many users.
As an object server, GemStone must address the same key issues as conventional information storage systems that support multiple concurrent users. For this reason, GemStone’s Smalltalk includes classes for:
You should be aware of a few differences between GemStone Smalltalk and client Smalltalk in syntax and in the behavior of some of the classes. A summary of these differences can be found in Appendix B.
GemBuilder’s programming environment provides tools for programming in GemStone Smalltalk. The following tools are described in detail in Part 2 of this manual:
Many GemStone users start with an application they have already written in Smalltalk. Their mission is to transform that application into one that makes meaningful use of GemStone’s features: persistence, multiuser access, security, integrity, and the ability to store and manage large quantities of information.
As a GemStone programmer, your application design and porting efforts involve the following tasks:
This section gives you an overview of these steps and points you to the chapters that discuss these topics in detail.
Your application will typically have two kinds of objects: those that must persist between sessions and be shared among users, and those that represent a transient state. Your first task is to identify the objects that make up your application and decide which ones need to be stored and shared. Making objects persistent unnecessarily can degrade performance and complicate programming.
Use the GemStone server to store those objects that need to exist between sessions and must be shared with other users. For example, objects representing information in your application such as financial statements, employee health records, or library book cards would certainly require storage in the server. Some methods for manipulating the persistent data can also be usefully coded in GemStone Smalltalk and stored in GemStone for improved efficiency.
You don’t need to store transient session objects that no one else will ever need on the server; such objects can remain in the client. For example, suppose you generate a report from the financial statements stored in GemStone. Once you view or print the report it has served its purpose; the next time you need a report you will generate a new one. The report and its component objects can exist simply as client Smalltalk objects; they don’t need to be stored in GemStone. However, you might want the classes and methods used to build the report to be stored in GemStone so that others can use them.
Certain objects can be considered your organization’s business objects. Business objects contain the data that give your organization its strategic, competitive advantage; their instance variables contain information about the business process that they model, and their methods represent actions involved in conducting business. Keeping your business objects centralized and stored separately from the applications that access them allows your organization to serve the needs of all users, while still enforcing consistency and maintaining control of critical information.
What security challenges does the application pose? Determine the strategy you will use to handle those challenges. Does access to certain objects need to be restricted to only certain authorized users? Many of your business objects may fall into this category. If so, who should be authorized to access them, and how? Do your users fall into groups with different access needs? Will anyone need to execute privileged methods? The earlier you lay the groundwork for your security needs, the easier they will be to implement. Security is discussed in detail in Chapter 6.
Once you’ve decided how to partition your application objects, you will want to set up connections between the objects that will reside on the client and those that will reside on the server so that GemBuilder can automatically manage changes to them and understand how to update them properly. This connection is established by making sure a connector is defined for those objects.
A connector connects not only the immediate object but also all those objects that it references, so you don’t need to define a connector for every object in your application that you want to store in the GemStone server. Instead, you should begin by identifying the subsystems in your application that define persistent objects, and then identifying a root object in each subsystem to target with a connector. You can find further discussion of connectors in Chapter 4.
Another decision you need to make involves transactions: when to commit and how to handle the occasional failure to commit. Do you want to use locks to ensure a successful commit? If so, identify the places in your application where you must acquire the locks. Concurrency control and locking are discussed in more detail in Chapter 5.
If, after you have built your application, you find that its performance does not meet your expectations, you have a variety of ways to improve matters.
One of the most powerful single things you can do to improve performance is to move some of the behavior from the client to the GemStone server and let the GemStone Smalltalk execution engine do the work. This approach reduces network traffic, which is a prime cause of slow performance.
Which methods might best be executed on the GemStone server? GemStone already contains behavior for many of the common Smalltalk kernel classes and, as mentioned earlier, the syntax and class hierarchy of GemStone’s Smalltalk language are so similar to those of other Smalltalks that the porting effort is likely to be relatively simple. Performance issues in general are discussed in Chapter 9. Moving execution to the GemStone server is discussed in the section entitled Locus of Execution.
Finally, you can configure the GemStone object server for maximum performance, given the details of your application and environment. GemStone server configuration parameters are discussed in detail in the GemStone System Administration Guide. In addition, the GemStone Programming Guide gives a variety of tips in the chapter entitled “Tuning Performance.”
GemBuilder is provided in the form of parcels named GbsRuntime, GbsTools, and CstMessengerSupport.
GemBuilder adds many classes and methods to your client Smalltalk image. Some of these are public, which means that they are designed to be referenced directly from your applications. GemStone avoids changing public classes and methods from release to release. Many GemBuilder classes and methods are considered private; they are used to implement the internal workings of GemBuilder and are not designed to be referenced directly from applications. Avoid using private classes and methods because they may have undocumented side effects, and because they are subject to change from release to release.
A GemBuilder class is private if its name begins with the prefix Gbx.
All methods on private GemBuilder classes are considered private, unless the class comment indicates otherwise.
A GemBuilder method on a public class can be marked private in any of several ways:
In general, we encourage you to use in your applications only GemBuilder classes and methods that are documented in this User's Guide, which describes the preferred way to accomplish tasks. Other public classes or methods may be obsolete but kept for backward compatibility.
In your code, do not define methods starting with “gb”. Methods with this prefix are reserved for GBS.
GemBuilder may include features that are deprecated in the current release. This indicates that although the feature is still functional, it may be removed in a future release. In your applications, you should eliminate any dependencies on deprecated GemBuilder features.
You can find all deprecated features of GemBuilder by browsing the senders of #deprecated:.
To help you determine whether your application uses any deprecated features, GemBuilder by default raises a GemStone.Gbs.GbsInterfaceError whenever a deprecated feature is used. The description of the GbsInterfaceError gives information about the deprecated feature that was being used.
If your application does not have an active handler for GbsInterfaceError when a deprecated feature is used, a walkback dialog will open. Once you've noted information about your application's use of the deprecated feature, you may proceed from the walkback or debugger, and your application will continue. This is a useful technique for a developer testing for use of deprecated features.
Once you've noted a particular use of a deprecated feature, you can avoid further walkbacks from that use until you are able to remove that use from your application. You can do this by adding a handler for the GbsInterfaceError that resumes the exception, at the point in your application that the deprecated feature is used.
You may also set the GemBuilder configuration parameter deprecationWarnings to false, as described in Chapter 10. When deprecationWarnings is false, any code in the client image may use any deprecated GemBuilder feature without raising a GbsInterfaceError.