ObjectStore Java API User Guide
Chapter 3

Using Sessions to Manage Threads

This chapter provides information about how to manage the threads in your application. Sample code that uses threads is in COM\odi\demo\threads.

This chapter discusses the following topics:

How Sessions Keep Threads Organized

Creating Sessions

Working with Sessions

Associating Threads with Sessions

Working with Threads

Which Threads Can Access Which Persistent Objects?

Description of ObjectStore Properties

Description of Concurrency Rules

How Sessions Keep Threads Organized

For a thread to use ObjectStore, it must be associated with a session. To use threads with ObjectStore, you must create at least one session and you must understand how to work with sessions.

If you try to use the ObjectStore API and you have not created a session, ObjectStore throws ObjectStoreException.

This section discusses the following information about sessions:

What Is a Session?

A session allows the use of the ObjectStore API. ObjectStore uses the abstract COM.odi.Session class to represent sessions.

Your application must create a session before it can use any of the ObjectStore API. After a session is created, it is an active session. A session remains active until your application or ObjectStore terminates it. After a session is terminated, it is never used again. You can, however, create a new session.

A session creates a context in which you can create a transaction, access one or more databases, and manipulate persistent objects.

Concurrent sessions

In a single Java VM,

If you are using ObjectStore, separate Java virtual machines can each run their own session at the same time. If you are using PSE Pro, separate Java virtual machines can each run multiple sessions at the same time. However, the default behavior is that at any one time only one Java VM process can access a database. See Description of Concurrency Rules.

How Are Threads Related to Sessions?

At any given time, an active session has zero or more associated threads. Any number of threads can join a session. Each thread can belong to only one session at a time.

At any given time, each thread is either joined to a single session or not joined (not associated) with a session. A thread that is not associated with a session can join a session. A thread that is associated with a session can leave the session to end its association with that session. It can rejoin the session at a later time or it can join some other session.

For a thread to use the ObjectStore API, it must be automatically or explicitly associated with a session. All threads that join the same session cooperate with each other. ObjectStore does not prevent cooperating threads from accessing the same object. Consequently, it is your responsibility to identify code segments that must be synchronized. To successfully call the Session.join() method to join a session, a thread must not already be associated with any session.

Current thread and current session

The current thread is the thread that you are making a call from. The current session is the session the current thread belongs to.

What Is the Benefit of a Session?

The benefit of a session is apparent when you want to have more than one session. Two sessions in the same Java process allow you to perform two distinct activities that involve ObjectStore. Each session has a clean, isolated view of the database. If you want to have two or more independent transactions going on at the same time, you can use two or more sessions. Concurrent sessions can be accessing the same database or different databases.

When two sessions are accessing the same object in the database, there are two distinct persistent objects. Each session has its own persistent object, which is a copy of the object in the database. At least initially, these two persistent objects have the same content.

Each session has its own set of persistent objects and API objects. In most circumstances, the threads of session A are not allowed to operate on the persistent objects of session B. An exception to this rule is described in Multiple Representations of the Same Object.

Independent threads

A need for many different independent transactions normally arises because you have many Java threads with different things going on in each one. Typically, this happens with a multithreaded application server, in which there are many threads. Each thread serves a different client, so you might want to have many threads. Each thread runs a separate transaction. Each thread is separate from each other thread.

Cooperating threads

On the other hand, there are times when you have multiple threads that are cooperating on some database task, and must operate on the same objects at the same time. In this case, you might want two different Java threads to participate in the same transaction.

Controlling which threads cooperate

Sessions allow you to control which threads cooperate in a transaction and which threads work in independent transactions. A session groups together a set of cooperating threads. Each session has a sequence (in time) of transactions, and a set of associated threads that participate in these transactions.

There is a many-to-one relationship between threads and sessions. That is, any number of threads can belong to one session.

Example of cooperating threads

A common case of cooperating threads arises when you are writing a Java applet. In an applet, there are calls to different parts of your program in different threads. You have to specify for ObjectStore that all these threads are part of the same session. This allows them to operate on the same objects and in the same transactions. A similar situation exists when you use RMI and CORBA servers. That is, there is a control mechanism that calls your methods in different threads.

What Kinds of Sessions Are There?

An active session can be a global session or a nonglobal session. ObjectStore provides two kinds of sessions because, when you only need one session, there are many things ObjectStore can do for you automatically.

Joining threads to sessions

As mentioned earlier, before you can use ObjectStore, you must create a session. For a thread to use ObjectStore, it must join a session. In a global session, an unassociated thread that makes a call to the ObjectStore API automatically joins the session. In a nonglobal session, this happens only when the call implies the session. See Rules for Automatically Joining a Thread to a Session. Otherwise, you must explicitly add the thread to a session.

Number of sessions

When there is an active global session, it is the only session in the Java VM. With PSE Pro and a future release of ObjectStore, you can have multiple nonglobal sessions or one global session in a Java VM. In the current release of ObjectStore and with PSE, there can be one session in a Java VM. It can be global or nonglobal.

Global sessions

Global sessions make programming easier, because you do not need to know the ObjectStore APIs for associating threads with sessions. All threads that make ObjectStore API calls automatically join the one global session.

The drawback is that you can only have one session. If you ever change your program in the future to use multiple sessions, you might have to go back and put in API calls to associate threads with the appropriate session. If you think you might use multiple sessions in the future, it would probably be a good idea to prepare for that by using a nonglobal session, and explicitly joining the session in each thread.

Note: Automatic joining of threads to a global session is not working in this release. You must explicitly join a thread to a session. See ObjectStore Java Interface Release Notes, Known Problems, Threads Are Not Being Automatically Joined to Sessions.

Creating Sessions

When you create a session, you initialize ObjectStore for use by the threads that become associated with that session. There are three ways to create a session:

Regardless of how you create a session, there are a number of ObjectStore properties you can specify when you create the session. These properties determine how ObjectStore behaves in a variety of situations.

Creating Global Sessions

When the session is a global one and a thread that is not associated with the session calls an ObjectStore API, ObjectStore automatically joins the thread to the session. After you create a global session, you do not need to be concerned about joining threads to the session.

To create a global session, call the Session.createGlobal() method. The method signature is

public static Session createGlobal(String host, 
      java.util.Properties properties)
This method creates and returns a new session and designates the session as a global session. There are no threads joined to this session yet. Any thread, including the thread that creates the session, automatically joins the session the first time the thread uses ObjectStore.

ObjectStore ignores the first parameter; you can specify null. The second parameter specifies null or a property list. See Description of ObjectStore Properties.

If you try to create a global session when there is already an active session, ObjectStore throws ObjectStoreException.

To obtain a global session, call Session.getGlobal(). The method signature is

public static Session getGlobal()
If the global session is active, ObjectStore returns it. Otherwise, ObjectStore returns null.

Creating Nonglobal Sessions

You can create a nonglobal session. The difference between a global and nonglobal session is that in a nonglobal session

Joining threads to sessions

For ObjectStore to automatically join an unassociated thread to a nonglobal session, the thread must be making an ObjectStore API call that implies a session. See Rules for Automatically Joining a Thread to a Session. You must explicitly join a thread to a session before that thread can call an ObjectStore API that does not imply a session. See Explicitly Associating Threads with a Session.

Method signature

The method signature for creating a nonglobal session is

public static Session create(String host, 
      java.util.Properties properties)
This method creates and returns a new session. ObjectStore ignores the host argument; specify null. The second argument specifies null or a property list. See Description of ObjectStore Properties.

ObjectStore does not join the calling thread to the session.

Session name

ObjectStore generates a name for the session and never reuses that name for the lifetime of the process in which the session was created. If you want to specify a particular name, use the following overloading to specify a unique session name:

public static Session create(String host, 
      java.util.Properties properties,
      String name)
ObjectStore uses the session name in debugging messages. The Session.getName() method returns the name of the session.

Exception conditions

If you call Session.create() when there is an active global session, ObjectStore throws ObjectStoreException. If you are using ObjectStore, and you call Session.create() when there is an active nonglobal session, ObjectStore throws FatalApplicationException.

Creating a Nonglobal Session with ObjectStore.initialize()

In previous releases of ObjectStore, the only way to create a session was to call the ObjectStore.initialize(host, properties) method. In this release, this method is provided for compatibility with earlier releases. This method might be deprecated in a future release. The method signature is

public static boolean initialize(String host,
      java.util.Properties properties)
This method creates a new session, joins the calling thread to the session, and returns true. The host argument can be null. The second parameter specifies null or a property list. See Description of ObjectStore Properties.

Comparison with Session.create()

When you use the Session.create() method in place of the ObjectStore.initialize(host, properties) method, you must also call the Session.join() method. While the ObjectStore.initialize(host, properties) method starts a session and joins the calling thread to the session, the Session.create() method only starts the session. It does not join the calling thread to the session.

False return value

When the three conditions listed below all exist, the ObjectStore.initialize() method returns false to indicate that it did not start a new session.

Exception conditions

If the calling thread already belongs to a session, but the host value specified in the initialize() method and the host value specified when the session was created are not the same, ObjectStore throws IllegalArgumentException.

If there is already a global session, ObjectStore throws ObjectStoreException.

If there is already an active session, ObjectStore throws FatalApplicationException.

Working with Sessions

After you create a session, you need to know how the session functions with regard to transactions. You also need to know about the operations you can perform on the session. This section discusses

Sessions and Transactions

At any given time, a session has one associated transaction in progress or it does not have any associated transaction. Each transaction is associated with exactly one active session.

When a session is created, there is no associated transaction. While a session is active, an application can start and then commit or abort one transaction at a time per session. Over time, a session is associated with a sequence of transactions.

If there is a transaction in progress when an application or ObjectStore shuts down the session, ObjectStore aborts the transaction as part of the shutdown process.

Within a session, multiple databases can be open at the same time.

All transactions can access the same database. All sessions must have read-only transactions against that database.

See also Description of Concurrency Rules.

Transaction in progress?

To determine whether or not there is a transaction in progress, call the Session.inTransaction() method. The method signature is

public boolean inTransaction()
If there is a transaction associated with the session, this method returns true. If there is no transaction associated with the session, this method returns false. If the session has been terminated, ObjectStore throws ObjectStoreException.

Obtaining associated transaction

To obtain the transaction associated with a session, call the Session.currentTransaction() method. The method signature is

public Transaction currentTransaction()
If the session has been terminated, ObjectStore throws ObjectStoreException. If no transaction is associated with the session, ObjectStore throws NoTransactionInProgressException.

Obtaining transaction's session

To obtain the session associated with a transaction, call the Transaction.getSession() method. The method signature is

public Session getSession()

Shutting Down Sessions

An application can shut down sessions. One reason you might want to shut down a session is to release the Java objects associated with the session.However, shutting down a session does not release all resources used by the C++ client. Such resources are released only when the application exits.To shut down a session, call the Session.terminate() method. The method signature is

public void terminate()
It does not matter whether the session is a global session or a nonglobal session. ObjectStore shuts down the session. If there are no other sessions, no thread can use the ObjectStore API until there is a new active session. The terminated session is never reused. If you are using ObjectStore, you must start a new session before you can use the ObjectStore API again.

Transaction in progress

If the session you shut down has an associated transaction, ObjectStore aborts the transaction. If the session has already been terminated, ObjectStore does nothing. If the session has any associated threads, ObjectStore causes them to leave the session. If the session has an open database, ObjectStore closes it.

ObjectStore.shutdown()

In previous releases, the way to shut down a session was to call the ObjectStore.shutdown() method. This method is maintained in this release for compatibility with earlier releases. It might be deprecated in a future release.

If ObjectStore throws FatalException, this shuts down the session.

Obtaining a Session

You can obtain a session with a call to any of the methods listed below:

Determining If a Session Is Active

To determine whether or not a session is active, call the Session.isActive() method. The method signature is

public boolean isActive()
If the session is active, this method returns true. If the session has been terminated, this method returns false.

Associating Threads with Sessions

To help you associate threads with sessions, this section discusses

There is a bug in the software that prevents threads from automatically being joined to sessions. As a work around, you must explicitly join each thread to a session. See the release notes for details. This bug will be fixed in a future release.

Automatically Joining Threads to a Session

Whether a thread can automatically join a session depends on

Global sessions

When there is a global session, an unassociated thread that makes a call to the ObjectStore API automatically joins the global session, if necessary. In the following situations, it might not be necessary to join the thread to the session:

Nonglobal sessions

In a nonglobal session, ObjectStore automatically joins threads to the session when the call from the thread implies that session. This means that the call specifies an argument that is already associated with that session. This includes the object on which the method is invoked.

After ObjectStore automatically joins a thread to a session,

Associating a Persistent Object with a Session

How does an object become associated with a session? It happens implicitly. Assume that a thread is already associated with a session. This associated thread successfully calls an ObjectStore API. If there are any objects that result from that call, ObjectStore associates them with the session that the calling thread belongs to.

As a result of explicit and implicit association, a session provides a context for a set of persistent objects, and a set of ObjectStore API objects, such a Database objects and a Transaction object.

The session defines a namespace. The namespace defines unique names (and consequently identities) for databases, segments, transactions, and persistent objects. While it is possible for threads in different sessions to share objects, doing so is incorrect and usually results in exceptions.

If the thread in which an object was materialized leaves the session, the object remains associated with the session.

Rules for Automatically Joining a Thread to a Session

Because of the associations between objects and a particular session, some API calls imply a session. If there is no global session,

If a thread associated with one session makes a call that implies some other session, ObjectStore throws ObjectStoreException.

Examples of Calls That Imply Sessions

A call that implies a session is a call that specifies an argument that is already associated with a session. It can also be a call in which the object on which the method is called is associated with a session. When these calls are in a thread that is not associated with a session, ObjectStore automatically joins the thread to the session with which the argument is already associated. It does not matter whether it is a global or nonglobal session. Some examples of API calls that imply a session follow:

Examples of Calls That Do Not Imply Sessions

A call that does not imply a session is a call that does not specify an argument that is associated with a session. When these calls are in a thread that is not associated with a session, ObjectStore cannot automatically join the thread to a session, if it is a nonglobal session. Consequently, the call fails and ObjectStore throws ObjectStoreException. Some examples of API calls that do not imply a session follow:

Explicitly Associating Threads with a Session

To explicitly join a thread to a session, you can call the following methods:

Session.join()

To explicitly associate a thread with a session, call the Session.join() method. The method signature is

public void join()
This associates the current thread (the thread that contains the call to join()) with the session on which the join() method is called.

If the session has been terminated, or if the thread making the call is already associated with that session or some other session, ObjectStore throws ObjectStoreException.

To join a thread to a session for a bounded duration of time, try something like this:

Session session;
session.create(null, myproperties);
try {
      session.join();
      ...;
      ...;
      ...;
}      finally {
            session.leave();
}

ObjectStore.initialize()

In previous releases of ObjectStore, the only way to join a thread to a session was to call the ObjectStore.initialize(targetThread) method. In this release, this method is provided for compatibility with earlier releases. This method might be deprecated in a future release. The method signature is

public static boolean initialize(Thread targetThread)
If the specified target thread is already joined to a session, this method joins the current thread to that session and returns true. If the current thread is already joined to the target thread's session, this method returns false.

If the target thread is null, ObjectStore throws IllegalArgumentException. If the target thread is not associated with a session, ObjectStore throws ObjectStoreException, whether or not the session that the target thread was previously associated with is still active.

It does not matter whether or not the target thread has a transaction in progress. You can call ObjectStore.initialize(targetThread) at any time.

Working with Threads

After you associate a thread with a session, it is important to understand how to use the thread within the framework of a session. To that end, this section discusses

Cooperating Threads

All threads associated with a particular session cooperate with each other. That is, they

For example, suppose thread A and thread B are cooperating threads (that is, they belong to the same session). A and B are running asynchronously. Each thread is issuing a sequence of operations and these sequences are interleaved in an unpredictable fashion.

For ObjectStore, it is as if these operations are all coming from the same thread. It does not matter which operation comes from A and which operation comes from B. ObjectStore views the operations as being in a single sequence, because they are issued from cooperating threads.

If A or B starts a transaction, it does not matter which thread issues the call. The transaction begins for both threads regardless of which thread actually starts the transaction. Any changes performed by A or B during the transaction are visible to both threads and can be acted on by either thread. Similarly, if A commits the transaction, it is just as if B commits the transaction. So B must be in a state where it is okay to commit the transaction. A and B must cooperate.

Noncooperating Threads

Threads that do not belong to the same session cannot share transactions, persistent objects, or locks on data, and cannot view the same state of the database. Threads that belong to different sessions are noncooperating threads. With ObjectStore, a different session belongs to a different process. With PSE Pro, a different session can belong to the same or a different process.

Two or more noncooperating threads can open the same database at the same time and access the same root object. If two or more noncooperating threads access the same object in the database, there are an equivalent number of distinct instances of the persistent object - one for each thread. The identity test, ==, does not show them to be identical.

Noncooperating threads can experience deadlock.

Synchronizing Threads

Your application is responsible for synchronizing activity among cooperating threads when the transaction is committed or aborted. In general, your application must avoid accessing the database while a thread is committing the transaction and until a cooperating thread starts a new transaction. If a transaction is aborted, cooperating threads might need to retry database operations.

Additional information about synchronizing threads is in Multiple Cooperating Threads.

Removing Threads from Sessions

A thread can leave a session at any time, including while a transaction is in progress. This does not affect the transaction, nor any threads that are still joined to that session. With or without a transaction in progress, it is okay if there are no threads associated with a session. The session does not terminate. A thread can join a session later to finish the transaction. If no thread ever does that, ObjectStore aborts the transaction when the session terminates.

To end the association of a thread with a session, call the Session.leave() method. The method signature is

public static void leave()
After you execute this method, the current thread is no longer joined to the session. If the current thread is already not associated with the session on which the method is called, ObjectStore throws ObjectStoreException.

If your application or ObjectStore shuts down a session, ObjectStore causes any associated threads to leave the session before it performs the shut down.

You can also call ObjectStore.shutdown() to remove a thread from a session. However, this method also shuts down the session when it is called on the last thread in the session.

If a thread is associated with a session and the thread terminates, it automatically leaves the session.

Threads That Create a Session

There is nothing special about the thread that creates a session. This thread can leave the session and any threads associated with that session can continue operating.

When your application calls the Session.createGlobal() or Session.create() method, ObjectStore does not associate the thread that calls the method with the newly created session. For that thread to join the new session, it must call the Session.join() method.

Other Threads

A thread that does not belong to a session cannot use the ObjectStore API. This rule has a few exceptions. A thread must not be associated with a session when it calls

A thread need not be associated with a session to successfully call Session.isActive().

If a session has a transaction in progress, a thread that is not associated with that session must not use persistent objects that belong to that session. See Which Threads Can Access Which Persistent Objects?.

If a session does not have a transaction in progress, any thread, including threads that do not belong to that session, can access persistent objects to the degree they were left visible when the application committed or aborted the transaction. See Ending a Transaction.

Determining If ObjectStore Is Initialized for the Current Thread

You can use the Session.getCurrent() method to determine whether or not ObjectStore is initialized for the current thread. The method signature is

public static Session getCurrent()

This method returns the session with which the current thread is associated. If the current thread is not associated with a session, this method returns null.

Which Threads Can Access Which Persistent Objects?

Each persistent object is associated with exactly one session. Any modification to the state of a persistent object must be done by a thread that cooperates in the session to which the persistent object belongs.

After you terminate a session, the persistent objects and API objects that were associated with it when it was terminated continue to be associated with the terminated session. One exception to this is when you call the Database.close() method with a true argument. This causes the persistent objects to be retained as transient objects, which are not associated with any session.

The information in this section is provided to help you ensure that threads access the correct objects. This section discusses these topics:

Multiple Representations of the Same Object

When you have multiple sessions, it is possible to have multiple persistent objects that represent the same object in the database. For example, a thread belonging to session A accesses object X. Then a thread belonging to session B accesses object X. There are two persistent objects that represent X. Each one is a representation of the same object in the database. If you use the == operator on session A's X and session B's X, the result is that they are not identical; they are not the same object. Within a session, ObjectStore preserves object identity.

Example of Multiple Sessions

The following example shows some actions you can and cannot perform when you have multiple sessions. In this example, suppose you have

In threadA, you start a transaction and read the contents of a persistent object called objectA. Since threadA is associated with sessionA, objectA belongs to sessionA. You commit the transaction with ObjectStore.RETAIN_UPDATE.

At this point, in threadB you can read or modify objectA as long as there is no transaction in progress in sessionB. However, any modifications will be discarded when sessionA starts a transaction.

Application Responsibility

It is the responsibility of the application to ensure that noncooperating threads act on persistent objects only in the ways allowed when a transaction is not in progress.

If you have a Java static variable that contains a persistent object and there are two separate sessions, you must decide which session owns the static variable. In other words, if there is a Java static variable whose value is a persistent object, that persistent object is associated with one session.

Effects of Committing a Transaction

When a thread commits a transaction, it affects only those persistent objects that belong to the same session that the thread belongs to.

Caution

You must ensure that an object never refers to an object that belongs to a different session. This is crucial because transitive persistence (performed when committing a transaction) must never reach an object that belongs to another session. If it does, ObjectStore throws ObjectStoreException.

Array objects

When a thread commits a transaction, if ObjectStore reaches an object whose class does not implement IPersistent, ObjectStore treats the object as a transient object and migrates it to a database. This works correctly for immutable classes such as Integer and String. For array objects, this can cause unpredictable results, because one session might modify the object while another session is using the old contents.

API Objects and Sessions

Each ObjectStore API object is related to one session. These metaobjects are

If you open the same database from two noncooperating transactions, each session has its own Database object to represent the database. These Database objects are not identical, that is, == returns false.

If you try to use a database in the wrong session, ObjectStore throws ObjectStoreException.

Description of Concurrency Rules

ObjectStore allows multiple readers or one writer of an object at any given time. The term one writer implies one session in any process. In a session, two cooperating threads that are both updating an object count as one writer. Two threads from different processes do not cooperate and, therefore, count as two writers.

If you use Multiversion Concurrency Control (MVCC), there can be one writer and multiple readers.

See also Handling Deadlocks.

Granularity of Concurrency

ObjectStore locks data at the page level. ObjectStore acquires a read lock on the object the first time the Java application reads or writes the contents of the object in a transaction. When that happens, the underlying C++ ObjectStore acquires a read lock on all pages used to store the object, as well as additional locks on other internal data structures (the info segment and schema segment). There is also Java-specific metadata that gets locked.

On Solaris and Windows, the size of a page is 4 KB.

Converting Read Locks to Write Locks

When a Java application modifies an object for which it already has a read lock, ObjectStore does not necessarily convert the read lock to a write lock immediately. The ObjectStore setLazyWriteLocking() method controls this behavior. If lazy write locking is true (the default) then ObjectStore only acquires write locks when it attempts to write the modified contents of the object to the database. That occurs either at commit time or when and if the application calls ObjectStore.evict() on the modified object.

Description of ObjectStore Properties

When you create a session, you can specify a properties argument. This section provides the following information about this argument:

About Property Lists Relevant to ObjectStore

When you create a session, there are two relevant property lists.

Finding the value of a property

To find the value of a property, ObjectStore checks the java.util.Properties object. If it provides a value, ObjectStore uses it. If it does not provide a value, ObjectStore checks the system property list.

Passing a property value

When you want to pass a property value to the method that creates a session, you typically put it in the java.util.Properties object that is an argument to the method that creates the session.

There is only one system property list for each Java VM. If there are multiple sessions in the same Java VM, they all use the same system property list. For more information about system properties, see System.getProperty, in section 20.17.9 of the Java Language Specification.

Defining a system property

All ObjectStore property names start with COM.odi. You can pass in property information by defining it as a system property. For example:

Properties props = System.getProperties();
props.put("COM.odi.useDatabaseLocking", "true");
Session session = Session.create(null,props);
There is also a System.setProperties() method that resets the System property list.

The JDK allows you to specify a system property by including

-D parameter= value

on the java command line before the class name. Each such specification defines one system property. Not all Java virtual machines run this way.

Defining a Properties object

If you want to construct your own property list, the type of the property list argument is java.util.Properties. For example:

Properties props = new Properties();
props.put("COM.odi.useDatabaseLocking", "true");
Session session = Session.create(null,props);

Description of COM.odi.applicationNameCOM.odi.applicationName

Set the COM.odi.applicationName property to the name of the application for the current client. This allows users of the LockTimeoutBlocker class and the ossvrstat utility to retrieve information about clients involved in concurrency conflicts. When you set this property, it can provide information about your application to other clients.

Description of COM.odi.cacheSize

The COM.odi.cacheSize property specifies the size of the C++ client cache in bytes. The default is 8 MB. If the value is a String that starts with 0x or 0X, ObjectStore treats the value as a hexadecimal number. ObjectStore rounds the cache size down to the nearest whole number of pages.

For information about how to determine the optimum cache size, see the book ObjectStore Management, Chapter 3, OS_CACHE_SIZE environment variable.

Description of COM.odi.disableWeakReferences

The COM.odi.disableWeakReferences property defaults to "false". This means that ObjectStore uses the weak reference facility of the JDK. If you set this property to "true", it disables the weak reference facility and ObjectStore does not use it.

When you start the first session in a Java process, the setting of the COM.odi.disableWeakReferences property is in effect for the duration of the Java process. If you terminate the session and start another session with a different value for the COM.odi.disableWeakReferences property, the new value is ignored.

A weak reference to an object is a reference that does not prevent the object from being garbage collected by the Java VM's garbage collector. ObjectStore uses weak references in its internal object table to hold references to unmodified persistent objects. If your program does not have any references to a persistent object and the reference in the object table is the only reference, the object can be garbage collected. If the persistent object has been modified and the changes have not yet been saved, ObjectStore uses strong references. Strong references do not allow the object to be garbage collected.

The weak reference facility in the JDK 1.1 is implemented in such a way that it prevents unmodified persistent objects from being garbage collected. This is corrected in the JDK 1.2. To use your database with the JDK 1.2, you must upgrade it. See Upgrading Databases for Use with the JDK 1.2.

Description of COM.odi.migrateUnexportedStringsCOM.odi.migrateUnexportedStrings

The COM.odi.migrateUnexportedStrings property controls what happens when ObjectStore encounters a cross-segment reference to an unexported String object. If this property is not set or if it is set to true, ObjectStore creates a new String object that has the same value as the referenced object. ObjectStore places this new string in the same segment as the referring object and substitutes this new string for the referenced string. If this property is set to false, ObjectStore throws ObjectNotExportedException if it encounters a reference to a string in another segment and that string is not exported.

Description of COM.odi.ObjectStoreLibraryCOM.odi.ObjectStoreLibrary

COM.odi.ObjectStoreLibrary specifies the name of the native C++ library that contains the ObjectStore schema and native methods for the application.

If you use Java/C++ interoperability, you must specify this property. If you do not use any C++ libraries in your application, you do not need to specify this property. The standard library supports COM.odi.coll collections, which are Java peer objects. A custom library is needed for application-specific peer classes.

You must specify a name that is acceptable to System.Load.Library() and not an explicit path. The name should follow platform conventions for library names. If you do not specify this property, ObjectStore uses the standard library, which provides for primary Java objects but not for Java peer objects. If your ObjectStore Java application is accessing C++ classes, you want the library that provides for Java peer objects.

For additional information, see Developing ObjectStore Java Applications That Access C++, Chapter 4, Building the Application.

Description of COM.odi.password and COM.odi.user

COM.odi.user and COM.odi.password allow you to supply a user name and a password when the ObjectStore Server has Name Password set for the Authentication Required Server parameter.

Description of COM.odi.product

COM.odi.product allows you to run multiple simultaneous sessions against different Object Design Java products in the same Java VM. Each Object Design Java product runs in its own session.

You must separately obtain each Object Design Java product that you want to use. When you purchase ObjectStore, neither PSE nor PSE Pro is included. To use PSE or PSE Pro, you must have a copy of PSE or PSE Pro.

Your CLASSPATH environment variable must include an entry for each Object Design Java product that you want to use. For example, if you want to use ObjectStore and PSE Pro, you must have entries for both osji.zip and pro.zip in your CLASSPATH. The order of the entries does not matter.

When you use multiple Object Design Java products, they must be compatible with each other. If they are not, FatalApplicationException is thrown.

You can set the COM.odi.product property to one of the following three values (case is not significant):

The COM.odi.product property applies to one session; it is not global. In other words, each session has a product attribute. After you start a session, you cannot change the value of COM.odi.product for that session.

With the COM.odi.product property, a single process can run all of the following at the same time:

You can create a session without explicitly setting the COM.odi.product property. In this case, Object Design software checks the Java system property list. If it finds a value for COM.odi.product, it uses that value. If it does not find a value, the default is that the software looks for PSE Pro, then PSE, then ObjectStore, and uses the first product it finds.

There are many ways this feature can be useful. For example, an application can:

The use of COM.odi.product to copy data among databases created with different products requires several steps. For example, to copy data from a PSE database to an ObjectStore database, you must do the following in the PSE session:

1 Open the source database.

2 Read the objects you want to copy.

The ObjectStore.deepFetch() method is useful for doing this.

3 Commit the transaction with ObjectStore.RETAIN_READONY.

4 Close the source database and specify true to retain the persistent objects as transient objects.

If you do not close the database, the persistent objects remain associated with the session in which you read them. This prevents another session from storing them in another database.

Then, in the ObjectStore session, you must

5 Make the objects reachable from the destination database.

6 Commit the transaction.

ObjectStore uses transitive persistence to store all reachable objects in the destination database.

Here is an example of code that performs these steps.

import COM.odi.*;
import COM.odi.util.*;
import java.util.Properties;
class CopyToOSJI implements ObjectStoreConstants {
      public static void main(String[] args) {
      /*       Create some data in a PSE database and then read it out. */
            Properties properties = new Properties();
             properties.put("COM.odi.product", "PSE");
            Session.create(null, properties).join();
            Database database = Database.create(
                  "pse.odb", ALL_READ | ALL_WRITE);
            Transaction.begin(UPDATE);
            OSVector vector = new OSVector();
            vector.addElement(new Integer(3));
            vector.addElement(new Integer(4));
            database.createRoot("vector", vector);
            Transaction.current().commit();
            Transaction.begin(READONLY);
            vector = (OSVector)database.getRoot("vector");
            ObjectStore.deepFetch(vector);
            Transaction.current().commit(RETAIN_READONLY);
       /*       Close the database and specify true 
            to retain persistent objects as transient objects. */
            database.close(true);
            Session.leave();
      /*       Copy the data to an ObjectStore database. */
            properties.put("COM.odi.product", "ObjectStore");
            Session.create(null, properties).join();
            database = Database.create("osji.odb", 
                  ALL_READ | ALL_WRITE);
            Transaction.begin(UPDATE);
            database.createRoot("vector", vector);
            Transaction.current().commit();
            database.close();
      }
}

Description of COM.odi.stringPoolSize

The COM.odi.stringPoolSize property allows you to specify how many newly created strings ObjectStore maintains in the string pool for the current session. The default is "100".

When ObjectStore is about to migrate a string to the database, it first checks the string pool for an identical string. If it finds one, it uses the string that is already stored in the database instead of adding a new identical string to the database.

The information about which strings are available to be shared is maintained only for the current transaction. The strings that are available to be shared are maintained in a string pool. ObjectStore resets the string pool to empty at the start of each transaction.

For example, suppose you create two instances of a Person object in a transaction. In each instance, the value of the name field is Lee. If you store both instances in the database in the same transaction, ObjectStore adds only one instance of the string "Lee" to the database. This is true even though the Java VM might contain two instances of the string "Lee". When ObjectStore writes the first "Lee" string in the database, it notes it in the string pool. Before ObjectStore stores the next instance of "Lee" in the database, it checks the string pool to see if an identical instance is already in the database.

Continuing the example, suppose you use two transactions and you store one instance of Person in each transaction. The result is that there are two identical "Lee" strings in the database. This is because ObjectStore resets the string pool to be empty at the start of each transaction. Consequently, ObjectStore cannot reuse the "Lee" string from the previous transaction.

Caution

If you use ObjectStore.destroy() to destroy strings explicitly, you might want to turn off string pooling, so that you do not inadvertently destroy a string that is shared by different objects. Alternatively, you can use the persistent GC to reclaim strings when they are no longer referenced. Using the GC is usually preferable to explicitly calling destroy(), because it is safer to let the persistent GC collect unreachable strings. Also, this approach is often more efficient and results in less database fragmentation.

Description of COM.odi.trapUnregisteredType

The COM.odi.trapUnregisteredType property is useful for troubleshooting ClassCastExceptions. The default is that this property is not set, and it is usually best to use the default.

When ObjectStore encounters an object of a type for which it does not have information (that is, the type is unregistered), it checks the setting of the COM.odi.trapUnregisteredType property.

If the property is not set, ObjectStore creates an instance of the UnregisteredType class to represent the object of the unknown type. Your application continues to run as long as it does not try to use the UnregisteredType object. Often, this can be fine because your application has no need for that particular field. However, if you do try to use the object of the unregistered type, ObjectStore throws ClassCastException.

If COM.odi.trapUnregisteredType is set, ObjectStore does not create an UnregisteredType object. Instead, it throws FatalApplicationException and provides a message that indicates the name of the unregistered class. For additional information, see Handling Unregistered Types.



[previous] [next]

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

Updated: 10/07/98 08:44:58