ObjectStore C++ API Reference

os_notification

Objects of class os_notification represent notifications for sending and receiving. A notification object embodies a database location (os_reference), a signed 32-bit integer kind, and a null-terminated C string.

os_notification::os_notification()

os_notification(
      const os_reference& ref, 
      os_int32 kind=0, 
      const char *string=0
);
Notifications can be created using a constructor that specifies all these elements. The os_notification object copies its string argument when the object is created, and deletes the storage for the string copy when it is deleted.

os_notification();
Notifications can also be allocated in arrays (see os_subscription). The default constructor for os_notification produces an uninitialized notification.

os_notification::assign()

void assign(
      const os_reference& ref, 
      os_int32 kind=0, 
      const char *string=0
);
Notifications can be reassigned using the assign member function. This is most useful when allocating arrays of notifications:

When passing database locations to os_notification member functions, you do not need to explicitly convert to os_reference. You can pass pointers or os_Reference<X>. These are converted by C++ automatically.

You can retrieve the components of a notification using the following accessor functions.

os_notification::get_database()

os_database *get_database()const; 
Retrieves the database associated with the notification.

os_notification::get_reference()

os_reference get_reference()const; 
Retrieves the reference associated with the notification.

os_notification::get_kind()

os_int32 get_kind()const;
Retrieves the kind associated with the notification.

os_notification::get_string()

const char *get_string()const;
Retrieves the string associated with the notification.

notify_immediate and notify_on_commit member functions provide shortcuts for the static member functions also defined on this class:

void notify_immediate();
void notify_on_commit();
A public enumeration in class os_notification represents the maximum string length usable in notifications.

enum {maximum_string_length = 16383};
A public enumeration in class os_notification represents the maximum notification queue size.

enum {maximum_notification_queue_length = 512};

os_notification::_get_fd();

Returns a file descriptor that can be used to detect whether any notifications exist. The only legal operation on this file descriptor is to call select() or poll(), to determine if any data has been received. If data has been received, then a notification has been queued for this application. It can be retrieved using os_notification::receive().

After retrieving a notification, you can test for further notifications again using select() or poll(). (That is, os_notification::receive() resets the notification_fd to the not ready state unless there are further notifications pending.

This function is not available on all platforms and configurations. This is because file descriptors are not used portably on all platforms. If notifications are not delivered using an fd mechanism, this function returns -1.

Using this fd for any purpose other than poll() or select() could cause unexpected application behavior. The Cache Manager and/or Server could disconnect from the client.

os_notification::notify_immediate()

static void os_notification::notify_immediate(
      const os_reference &ref,
      os_int32 kind = 0,
      const char *string = 0,
      os_int32 *n_queued = 0
);
static void os_notification::notify_immediate(
      const os_notification *notifications, 
      os_int32 n_notifications = 1,
      os_int32 *n_queued = 0
);
Posts a notification to the object specified by ref. The database associated with ref must be open. The kind and string arguments are arguments sent to the receiving process.

Note: The kind argument must be greater than or equal to zero. Negative kinds are reserved for future use by ObjectStore.

If the string specified is null (0), it is received as an empty string ("").

If supplied, the n_queued argument is a signed 32-bit integer (or array of n_notification integers). This integer is set to the number of receiving processes to which notifications were queued. Note that because notifications are asynchronous, no guarantees can be made that the process will ever receive the notification. (The receiving process might terminate before receiving the notification, it might never check for notifications, the Server might crash, the Cache Manager might crash, or the notification queue could overflow.)

In the second (array) form of notify_immediate, the n_queued argument, if specified, is an os_int32 array at least n_notifications long. The elements of the array are set to the number of receiving processes for each notification specified.

Each call results in a single RPC call to each ObjectStore Server. It is significantly more efficient to make one call with an array of notifications than to make many calls with each notification.

If the caller does not require the n_queued information, it should leave n_queued defaulted to 0. This could result in better performance in future releases.

The notify_immediate operation is not atomic. That is, if an error is signaled, the status of notifications is undefined. For example, notifications might have been successfully delivered to one Server before a second Server signals an error with respect to its notifications.

os_notification::notify_on_commit()

static void os_notification::notify_on_commit(
      const os_notification *notifications, 
      os_int32 n_notifications = 1);
Queues a commit-time notification to the object specified by ref. The database associated with ref must be open, and there must be a transaction in progress. The notification is delivered when, if, and only if,

If the string specified is null (0), it is received as an empty string ("").

Notification delivery and commit are an atomic operation from the perspective of the process sending the notification. That is, if the commit succeeds, the notifications are guaranteed to be sent, even if the sending application crashes. Note however that the notifications themselves are transient, and might be lost if there is a Server failure, Cache Manager failure, notification queue overflow, or if a receiving process dies.

The notifications are matched with subscriptions immediately after the commit succeeds. Because of this, there is no way to determine how many processes have been queued to receive notifications.

If a deadlock occurs during a stack transaction, ObjectStore aborts and automatically restarts the transaction. In this case, because the transaction aborted, commit-time notifications are discarded, and execution resumes at the beginning of the stack transaction.

os_notification::notify_on_commit does not immediately perform an RPC call to the Server. If there are any calls to os_notification::notify_on_commit during a top-level transaction, and the transaction commits, there is one additional RPC call to each Server at commit time.

In some read-only transactions, the ObjectStore client does not normally have to communicate with Servers. If os_notification::notify_on_commit is called during such a read-only transaction, the Server must be contacted during the commit.

If a database is closed after a notify_on_commit but before committing the transaction, the notification will still be delivered on successful commit. The database must be open when notify_on_commit is called.

os_notification::queue_status()

static void os_notification::queue_status(
      os_unsigned_int32 &queue_size,
      os_unsigned_int32 &count_pending_notifications,
      os_unsigned_int32 &count_queue_overflows
);
Returns information on the notification queue for the current process. If count_pending_notifications is greater than zero, notifications are pending. This function can be used as a polling function to see if there are notifications without actually retrieving them. It does not lock out other ObjectStore operations in other threads.

Generally, applications should call this at least once after each notification is retrieved, to ensure that there are no queue overflows, and perform appropriate actions if they do occur.

Values returned are as follows:
queue_size
The size of the notification queue, as set by os_notification::set_notification_queue_size(), OS_NOTIFICATION_QUEUE_SIZE, or defaulted.
count_pending_notifications
The number of notifications currently in the queue. That is, notifications that have not yet been received by the process using os_notification::receive().
count_queue_overflows
The number of notifications discarded since the process started. A value of 0 indicates that no notifications have ever been discarded since this process began.

os_notification::receive()

static os_boolean os_notification::receive(
      os_notification *&notification,
      os_int32 timeout = -1
);
Gets the next notification from the notification queue, if available. If a notification is available, it returns true, and places the notification in the first argument. Otherwise, it returns false, and the first argument is unmodified.

If the notification queue is currently empty, the function waits as specified by the timeout argument. A value of -1 indicates to wait forever until a notification is received. A value of 0 indicates to return false immediately. A positive integer indicates to wait the specified number of milliseconds. On some platforms, this value is rounded up to the next higher number of seconds.

The notification returned is allocated dynamically in transient storage. When the application finishes using it, it can be deleted using the C++ delete operator. (This causes the notification string to be deleted as well.)

os_notification::receive() uses operating system primitives for waiting; it does not spin, polling for notifications. Users normally call this function in a separate thread that exists specifically to receive notifications.

Only one thread can call os_notification::receive() at any one time. It is an error to call it in multiple threads simultaneously.

Only os_notification::receive() and os_notification::queue_status() can be called asynchronously with other ObjectStore operations. All other APIs, including the os_notification accessors, are subject to normal thread-locking rules. This means that the retrieved notifications cannot be accessed in concurrent threads without locking out ObjectStore threads.

If os_notification::receive() is called before subscribing to notifications, it returns false immediately, regardless of the timeout argument. This is to avoid deadlocks in some situations involving multiple threads. To avoid this, ensure that os_notification::subscribe() or os_notification::_get_fd() is called before calling os_notification::receive(), or before launching a thread that calls os_notification::receive().

With long strings, os_notification::receive() might have to wait slightly for the entire string, even if timeout==0 is specified.

os_notification::set_queue_size()

static void os_notification::set_queue_size(os_int32u queue_size);
Sets the size of the notification queue for a process. It must be called prior to os_notification::subscribe() or os_notification::_get_fd(). If this function is not called, the queue size is determined by the value of the OS_NOTIFICATION_QUEUE_SIZE environment variable. If the environment variable is not set, the queue size is set to a default value, currently 50.

A public enumeration in class os_notification represents the maximum notification queue size.

enum {maximum_notification_queue_length = 512};
Notification queues are part of the ObjectStore Cache Manager process.

os_notification::subscribe()

            static void os_notification::subscribe(const os_subscription *sub, os_int32 count = 1);
            static void os_notification::subscribe(const os_database *db);
            static void os_notification::subscribe(const os_segment *seg);
            static void os_notification::subscribe(const os_object_cluster *clus);
            static void os_notification::subscribe(const os_reference &ref, os_int32 n_bytes = 1);
These functions all subscribe to notifications. You can subscribe to any notification in a database, segment, cluster, event range, or reference. A subscription in a database, segment, or cluster applies to all addresses in the database, segment, or cluster, even addresses that have not yet been allocated.

The first function lets you subscribe to one os_subscription, or an array of os_subscription. The count argument is the length of the array.

The database must be open. Closing the database immediately unsubscribes all locations associated with the database.

If a database location is subscribed more than once, the notification system behaves as if there were only one subscription on the location. That is, multiple subscriptions on a database location are ignored.

Each call results in a single RPC call to each ObjectStore Server. It is significantly more efficient to make one call with an array of subscriptions than to make many calls with each subscription.

The subscription operation is not atomic. That is, if an error is signaled, the status of subscriptions is undefined. For example, subscriptions might have succeeded on one Server before a second Server signals an error with respect to its subscriptions.

os_notification::unsubscribe()

            static void (const os_subscription *sub, os_int32 count = 1);
            static void os_notification::unsubscribe(const os_database *db);
            static void os_notification::unsubscribe(const os_segment *seg);
            static void os_notification::unsubscribe(const os_object_cluster *clus);
            static void os_notification::unsubscribe(const os_reference &ref, os_int32 n_bytes = 1);
These functions all unsubscribe database locations for notifications.

If a subscription was made on an entire database, the only way to remove it is to unsubscribe the entire database; you cannot selectively unsubscribe segments or database locations.

If a subscription was made on an entire segment, the only way to remove it is to unsubscribe the entire database, or unsubscribe the entire segment. You cannot selectively unsubscribe database locations within the segment.

If a subscription was made on a cluster or range, ranges can be selectively unsubscribed within the original cluster or range. Unsubscribing an unsubscribed database location has no effect.

Note that closing a database automatically unsubscribes all notifications for the database. Because notifications are processed asynchronously, an application might continue to receive notifications after having unsubscribed.

Each call results in a single RPC call to each ObjectStore Server. It is much more efficient to make one call with an array of subscriptions than to make many calls with each subscription.

The unsubscription operation is not atomic. That is, if an error is signaled, the status of unsubscriptions is undefined. For example, unsubscriptions might have succeeded on one Server before a second Server signals an error with respect to its unsubscription.

Additional notes
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 Modifying Network Port Settings of ObjectStore Management for specific details.

Notification errors
The notification APIs do not do complete validation of the arguments passed to them. Malformed arguments can therefore cause segmentation violations or other undefined behavior. See General ObjectStore Exceptions for details.

Utilities
ossvrstat currently prints statistics on the number of notifications received and sent by the Server.

oscmstat prints information on notifications queued for clients. This is useful in debugging applications that use notifications.

Detailed information on these user interfaces appears in ObjectStore Management.



[previous] [next]

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

Updated: 03/31/98 17:25:09