ObjectStore Java API User Guide
Chapter 11

Using the Notification Facility

The notification facility allows an application to notify one or more sessions that an event has taken place. Each notification is associated with a location in a database. Your application determines what constitutes an event. In general, an event is anything you want your application to notify other sessions about. For example, a modification to a particular object in a database can be an event.

This chapter discusses the following topics:

Background About How Notification Works

Creating Notifications

Subscribing to Receive Notifications

Sending Notifications

Retrieving Notifications

Reading Notifications

Managing the Notification Process

Background About How Notification Works

This section provides information about how the notification system works. It covers these topics:

What Is a Notification?

A notification is an ordinary transient Java object. A notification always specifies

When a session subscribes to receive notifications for a segment or database, the subscribing session receives any notifications for objects in the segment or database.

In Release 1.3, only one session is allowed in a single Java VM, so only one session can subscribe to a notification. In a future release, it is expected that there can be multiple sessions in the same Java VM. In this release, separate processes can simultaneously subscribe to receive notifications for the same locations.

What Is the Flow of a Notification?

An application creates a notification. Sessions that want information about events related to a particular location subscribe to notifications that specify the location of interest.

When there is an event that involves the location in a notification, the application uses the notification API to send the notification to the ObjectStore Server.

When the Server receives a notification, it determines which sessions are subscribed for that notification. The Server then queues messages to be sent to the receiving sessions. The Server returns the number of messages queued and then asynchronously sends notifications to the Cache Manager of the receiving sessions (the subscribers).

There is a queue inside the Cache Manager for each session on that host. When the Cache Manager receives a notification from the Server, it puts the notification into the queue of each of the subscribing sessions.

A session that subscribes to one or more notifications usually dedicates a thread to receive notifications. When this thread finds a notification in the Cache Manager's queue for that session, it removes the notification from the queue and returns it to the associated session, which performs an application-specific action.

Threads and Notifications

A session starts a thread whose sole purpose is to receive notifications. This thread calls Notification.receive() with an argument that specifies how long to wait for notifications. Each session has its own dedicated thread.

When a session receives a notification, it performs an application-specific action. For example, it might post a Windows message, modify the application's transient data structures, or otherwise queue the notification for processing by another thread. It then waits for the next notification.

The thread dedicated to receiving notifications typically does very little work. It might do queue management, for example, maintaining a priority queue of notifications for another thread, or coalescing similar notifications. However, processing should be minimal, so the Cache Manager notification queue does not overflow. Queue overflow can happen if many notifications arrive in quick succession. The thread receiving the notifications might not be able to keep up with the process of removing the notification from the queue and returning it to the session.

In contrast to most other ObjectStore APIs, Notification.receive() is not locked out when other threads are in ObjectStore operations. If the thread does not access persistent data or call other ObjectStore APIs, it can run entirely asynchronously.

Transactions and Notifications

An application can send a notification

Transactions are independent of immediate notifications, subscriptions, unsubscriptions, and notification retrieval.

The sending of commit-time notifications, however, is closely integrated with transactions. ObjectStore queues commit-time notifications inside a transaction, and sends them when the transaction commits. If the transaction aborts, the application never sends the commit-time notifications. This is useful when you want dispatch of the notification to be contingent on a database modification that becomes visible when a transaction commits.

There are no restrictions on transaction types. The enclosing transaction can be read-only or update. Databases can be opened read-only, update, or MVCC.

As always, database changes made by a session are not visible to other sessions until the transaction commits. Therefore, all notifications that indicate changes to persistent data should be made at commit time.

Security

To send or subscribe to notifications, a session must open the database that contains the referenced location. If a session does not open a database, it cannot send or receive notifications associated with that database. If you do not have permission to open a database, you cannot send or subscribe to notifications on objects in that database.

Within a database, notifications are not integrated with ObjectStore security. A session can subscribe to notifications and send notifications that reference database locations in any segment.

Creating Notifications

When an application creates a notification, the database that contains the referenced object must be open. It does not matter whether or not a transaction is in progress. However, an object that an application passes to a Notification method cannot be a stale object.

Descriptions of Constructors

The constructors for creating notifications have these signatures:

The location parameter specifies a persistent object. It indicates the location at the beginning of the object. You must specify a persistent object. It is not good enough for the location object to be persistence-capable. If the specified object is not persistent when you try to construct a notification, ObjectStore throws ObjectNotPersistentException. To avoid this, call the ObjectStore.migrate() method to store the object in the database before you create the notification.

You can specify a Java peer object if it identifies a persistent C++ object. See Developing ObjectStore Java Applications That Access C++, Chapter 3, Writing the Application.

The kind, data, and message parameters provide information about the event. Every notification has a kind parameter. If you specify a negative argument, ObjectStore throws IllegalArgumentException.

If you do not want to attach a message or data to the notification, specify null for the third argument when you create the notification, or do not specify a third argument. For example, the following two code fragments do exactly the same thing:

String a = null;
new Notification(foobar, 102, a);
new Notification(foobar, 102);
If you do specify a third argument, it is a sequence of bytes. For convenience, ObjectStore allows you to pass in a Java String instead of a sequence of bytes. ObjectStore uses UTF-8 encoding to encode message arguments into a sequence of bytes.

When ObjectStore sends a notification, it makes the kind parameter and the data or message parameter, if there is one, available to subscribers. If a notification includes a null string ("null"), it is received as an empty string ("").

Retaining References to Persistent Objects

A notification always contains a reference to a persistent object. You can create a notification in one transaction, and then use it in a subsequent transaction or between transactions.

To do so, you must ensure that the reference is not to a stale object. If it is, ObjectStore throws ObjectException.

To ensure a nonstale object, you can evict the referenced object or commit or abort the transaction with a retain type other than ObjectStore.RETAIN_STALE. If you evict the object so that you can still use it, but then you abort or commit the transaction with ObjectStore.RETAIN_STALE, this cancels the retain type specified for evict().

Maximum Data Lengths

For the byte[] data parameter in the constructor, the MAXIMUM_DATA_LENGTH variable specifies the maximum length of the byte array:

public static final int MAXIMUM_DATA_LENGTH = 16383
For the String message parameter, this variable specifies the maximum length of the UTF-8 encoding of the string. If the String is ASCII, the compression is one-to-one.

Restriction on data Argument Content

The C++ interface to ObjectStore treats the data argument as a C or C++ string, so there cannot be embedded zeros. If your application is directly providing a data array, it must ensure that there are no zeros in the data array. If your application is providing the data in the form of a string, it works correctly because the UTF-8 encoding of strings never uses zero bytes. If you try to construct a notification with a byte[] data array and you include a zero, ObjectStore throws IllegalArgumentException.

Subscribing to Receive Notifications

A session uses the Notification.subscribe() method to register to receive notifications for the specified location or within the specified segment or database. The database that contains the referenced object or segment must be open when a session calls the subscribe() method. These are the overloadings of subscribe():

The placement parameter can specify a database or segment. The subscribing session receives a notification if the application sends a notification that refers to an object in the specified segment or database.

The location parameter specifies a persistent object.

A session can subscribe to many locations, segments, and databases simultaneously. ObjectStore stores subscriptions in the ObjectStore Server for as long as the corresponding database is open for the associated session.

Discarding Subscriptions

When a session closes a database, ObjectStore discards any subscriptions in that session to notifications related to that database.

Unsubscribing from Notifications

A session can unsubscribe from particular notifications just as it can subscribe to them. The unsubscription is immediate. The Notification.unsubscribe() method has overloadings that are parallel to subscribe():

If you try to unsubscribe from a notification that you are not subscribed to, nothing happens.

Asynchronous processing

ObjectStore processes notifications asynchronously. Consequently, a session might unsubscribe from a particular notification but still receive notifications for that location because they were already queued.

The only way to cancel a segment or database subscription is to unsubscribe from that segment or database. You cannot unsubscribe from a segment or database by unsubscribing from the notifications about the objects in that segment or database.

Sending Notifications

An application can use any of the following methods to send notifications:

You can send one notification at a time or an array of notifications. You can send notifications immediately or when a transaction commits. If you wait to send a notification until a transaction commits, you ensure that a subscriber does not receive the notification until any associated change is visible in the database.

The object referenced in the notification cannot be stale and cannot have been destroyed.

Modification of an object does not cause a notification to be sent. A notification is sent only when the application program explicitly uses the notification API to send one.

Retrieving Notifications

The ObjectStore Server queues notifications in the Cache Manager that is associated with the subscribing session. It is up to the session to retrieve notifications from the Cache Manager. Typically, a session dedicates a thread to retrieve notifications from the queue. To do this, a thread calls Notification.receive(). The method signature is

public static Notification receive(int timeout)
The timeout parameter specifies the number of milliseconds to wait for a notification. Specify ObjectStore.WAIT_FOREVER to instruct the thread to wait forever. A value of 0 instructs the thread to return if there are no notifications in the queue.

The method returns a Notification object, or null, if there are no notifications in the allotted time. When the timeout parameter is ObjectStore.WAIT_FOREVER, ObjectStore never returns null.

When you call receive(), it does not matter whether or not a transaction is in progress. However, the thread from which you call receive() must be associated with a session.

A thread that calls the Notification.receive() method allows you to avoid polling your application. This method returns as soon as a notification is available, and until then it just waits. No polling is involved. The application is awakened when a notification arrives.

Reading Notifications

To extract the contents of a notification, use the following Notification class methods:

Managing the Notification Process

Managing the notification process involves consideration of the following:

Notification Queue

The Cache Manager maintains a queue of notifications for each session on a machine. To set the size of the queue, call Notification.setQueueSize(int queueSize). ObjectStore throws NotificationException if a session subscribes to a notification before calling this method. The new queue size must not exceed the value specified for the MAXIMUM_NOTIFICATION_QUEUE_LENGTH.

Nothing forces a session to retrieve or read notifications. A session can subscribe to notifications but never retrieve any.

To avoid resource exhaustion in the Cache Manager, the size of the notification queue for each client is fixed. If the Cache Manager receives a notification and the queue is full, ObjectStore discards the notification. This is called an overflow. Overflows do not cause any exception to be signaled and do not cause the application, the Cache Manager, or the Server to crash.

The Cache Manager keeps statistics on the notification queue that include

To obtain these statistics, you can call the following Notification class methods:

The information returned by these methods applies to only the session in which the method is called.

You can also use the ObjectStore utility oscmstat to obtain these statistics. The ossvrstat utility displays statistics on the number of notifications received and sent by the Server. See Chapter 4 in ObjectStore Management.

Performance Considerations

All notifications and subscriptions on a database go to the ObjectStore Server. The Server routes notifications to subscribed sessions through the Cache Manager, which queues the notifications for sessions. Because the Server acknowledges each notification, sending a notification requires a round-trip message to the Server.

Retrieving notifications only accesses shared memory and is very fast. If a session does not retrieve its notifications, the Cache Manager can run out of queue space. This causes the Cache Manager to discard notifications.

Every call to subscribe(), unsubscribe(), notifyImmediate(), and notifyOnCommit() requires one round-trip message to the ObjectStore Server.

If any commit-time notifications are queued during a transaction, there is an additional remote procedure call (RPC) to the ObjectStore Server during the commit operation.

Notifications are stored and forwarded in the Server, Cache Manager, and sometimes even in the receiving application. Therefore, delivery of notifications might not be particularly fast. Performance varies according to system load and the amount of notification processing. For example, delivery could range from milliseconds to several seconds.

As a general rule, if you plan your application to use notifications, you should not expect high throughput. Do not expect a client application to send or receive more than about ten notifications per second. In other words, do not use ObjectStore notification to meet high-speed requirements. The notification facility has a fairly simple design with limited buffering capability.

Network Service

When an ObjectStore application uses notifications, it automatically establishes a second network connection to the Cache Manager daemon on the local host. The application uses this connection to receive (and acknowledge the receipt of) incoming notifications from the Cache Manager. (Outgoing notifications are sent to the Server, not the Cache Manager.) See Chapter 1, Overview of Managing ObjectStore, in ObjectStore Management for specific information about defaults.



[previous] [next]

Copyright © 1998 Object Design, Inc. All rights reserved.

Updated: 10/07/98 08:46:23