C++ Interface Release Notes

Chapter 2

Changed Features

This chapter documents features of ObjectStore that have been either removed or changed for Release 6.0. These include

The following features are no longer supported:

For information about changes to the API, see Chapter 3, Changes to the API.

Database Format

The format of the ObjectStore database has changed for Release 6.0. To upgrade an existing ObjectStore database, you must use the dump/load facility, as described in the Advanced C++ API User Guide, Chapter 8.

dump/load facility
The dump/load facility is available in Release 6.0. However, the migration facility that is built on top of dump/load is not available for this Beta release.

Release 6.0 clients will not be able to access databases created by pre-Release 6.0 clients. However, the Release 6.0 Server will be able to manage databases created either by Release 6.0 clients or pre-Release 6.0 clients. This feature allows databases to be migrated from one release to another without the need for starting and stopping servers from different releases multiple times in order to upgrade databases.

Incompatible database format
The format of databases created with Beta versions of ObjectStore might not be compatible with the database format of subsequent betas or the GA release. Beta users should expect to have to discard databases that have been created with beta versions of the software.

Opening and Closing Databases

ObjectStore databases can be opened repeatedly without being closed, so long as each succeeding call to open() specifies the same mode: MVCC, read-only, or update. ObjectStore maintains an open count, which calls to open() increment and calls to close() decrement. The database is closed when the count reaches 0.

Other changes to the Open-Close API include

For detailed information about changes to the API, see the following:

MOP API

As previously announced, a small number of methods in the Metaobject Protocol (MOP) API are redundant and use of these methods is obsolete. Release 6.0 does not support these methods, which have been replaced by other methods from the same class. For more information, see the following:

Support for the C interface has also been removed from the MOP API.

Support for Persistent Unions

Previous to Release 6.0, users had to write their own discriminant functions when working with unions in persistent memory. Release 6.0 no longer supports discriminant functions. They have been replaced by

Also, Release 6.0 no longer supports objectstore::discriminant_swap_bytes(). This function was used to perform byte swapping inside discriminant functions when accessing databases created by clients with a different byte ordering. It is no longer needed.

The New APIs

The API for objectstore::set_union_variant() is

set_union_variant()
static void set_union_variant( 
      void *address, 
      const char *type_name, 
      os_unsigned_int16 variant 
); 
The arguments have the following meanings:

The API for objectstore::get_union_variant() is

get_union_variant()
static os_unsigned_int16 get_union_variant( 
      void *address, 
      const char *type_name 
); 
The arguments have the following meanings:

Using objectstore::set_union_variant()

objectstore::set_union_variant() must be called whenever a member object becomes active, including initially. The variant argument indicates the active member object; if no member object is active (that is, the union is uninitialized), it is set to 0.

Consider the following class declaration, which has a data member whose value is a union:

class kgraph { 
private:
      union kg_union { 
            kgraph* kg_kg; 
            os_int32 kg_int; 
      } kg; 
      os_int16 kg_type; 
public:
      kgraph()
      {
            kg_type = 0;
      }
      
      void set_kg( kgraph* new_kg) 
      { 
            kg_type = 1; 
            if (objectstore::is_persistent(this)) 
                  objectstore::set_union_variant( this, "kg_union", 1 ); 
            kg.kg_kg = new_kg;
      } 

      void set_int( int new_int ) 
      { 
            kg_type = 2; 
            if (objectstore::is_persistent(this)) 
                  objectstore::set_union_variant( this, "kg_union", 2 ); 
            kg.kg_int = new_int;
      } 

      os_boolean verify()
      {
            os_int16 uv = objectstore::get_union_variant( this, "kg_
union");
            if (kg_type != uv)
                  cout << "union variant verification failed: expected "
                       << kg_type << " but returned " << uv << endl;
            return (kg_type == uv);
      }
      
      static os_typespec *get_os_typespec();
};
Whenever either kgraph::set_kg() or kgraph::set_int() is called, the embedded call to objectstore::set_union_variant() records the currently active member object.

An exception occurs if any of the following is true:

Affiliation and Cross-Database Pointers

Previous to Release 6.0, you had to call os_database::allow_external_pointers() to allow a database to store pointers to other databases. Thereafter, you could write cross-database pointers to any other database. Each time you wrote the first pointer to a database, ObjectStore would implicitly update the pathname pool of this database with an entry for the new target database. This implicit behavior could result in concurrency bottlenecks that are difficult to predict.

In Release 6.0, implicit updates are replaced by explicit calls to the os_database::affiliate() method. This method affiliates this database with a target database by adding the path of the target to the pathname pool of this database. The affiliate() method must be called once for each target database.

affiliate() starts and commits a transaction if one is not already in progress. Until the end of the top-level transaction, the pathname pool of this database is write-locked and (if the deep argument is set to true) the pathname pool of the target database is read-locked. The pathname pool of this database is updated to include the target database.

New
The following methods have been added to the os_database API:

Removed
The following methods are no longer supported:

Also, the os_database_reference class has been removed; see os_database_reference.

Operator new Overloads

Release 6.0 provides two additional overloadings of operator new:

void *::operator new(size_t, os_cluster, os_typespec) 
void *::operator new(size_t, os_cluster_with, os_typespec) 

os_cluster Overload

The os_cluster overload of new tries to allocate storage in the specified cluster. If it cannot allocate sufficient storage for the object, it signals the exception err_cluster_full.

This overloading of new requires an os_cluster object; see os_cluster. If your program does not have one at hand, call os_cluster::of(object), which returns an os_cluster object for the cluster of object; see os_cluster::of(). If the object to be allocated is greater than 64K, it is allocated in a new cluster in the same segment as object; see Clusters and Allocation Size.

It is the user's responsibility to delete the os_cluster object.

os_cluster_with Overload

The os_cluster_with overload of new is useful grouping (clustering) related objects. It tries to allocate storage for an object as close as possible to another object; see os_cluster_with. To obtain an os_cluster_with object, call os_cluster::with(object); see os_cluster::with().

If the object to be allocated is greater than 64K, it is allocated in a new cluster in the same segment as object; see Clusters and Allocation Size.

Object Design recommends using the os_cluster_with overloading of operator new because it simplifies management of transient memory for the application. For example, the following invocation of new

foo* x = new( os_cluster::with( this ), foo::get_os_typespec() ) foo; 
does not require the user application to deallocate the os_cluster_with object returned by os_cluster::with().

Cache Manager

The following sections describe changes to the Cache Manager for Release 6.0.

Reduced commseg Size

The new Cache Manager has a substantially reduced commseg size. commseg is the shared memory region used to communicate the state about locks between client and Cache Manager. Previous to Release 6.0, the size of commseg varied; it was typically 266 KB but could grow depending on the operations performed by a client. In Release 6.0, its size is a function of the size of a client's cache, and it is allocated at client ObjectStore initialization time and will never grow beyond that size. The typical size of commseg in Release 6.0 for an 8-megabyte client cache (the default) is 64 KB.

TCP/IP Port Numbers

The new Cache Manager uses TCP/IP port numbers that do not conflict with the port numbers of the Cache Manager from previous releases of ObjectStore. The following TCP/IP port numbers are assigned to the Cache Manager:
51025

Client to Server communication

51041

Client to Cache Manager communication

51031

Cache Manager to Server communication

51050

Cache Manager notification communication

For other port designations and information about adjusting port numbers, see Managing ObjectStore.

Transactions

The following sections describe changes to ObjectStore's support for transactions. For changes to the os_transaction API, see os_transaction.

Global and Local Transactions

Release 6.0 supports both local and global transactions. By default, all transactions are local. All lexical transactions are always and only local. (A lexical transaction is delimited by the OS_BEGIN_TXN and OS_END_TXN macros.)

Dynamic transactions can be either local or global. To start a global transaction, call os_transaction::begin() with os_transaction::global specified as the last argument. The default is os_transaction::local.

The following paragraphs provide more detailed information about global and local transactions. For reference information about os_transaction::begin() and its arguments, see os_transaction::begin().

Global Transactions
For multithreaded applications that do not use the sessions facility, starting a global transaction in one thread causes all other concurrent threads to enter the same global transaction. For multithreaded applications that use the sessions facility, starting a transaction in one thread causes all other concurrent threads in the calling thread's current session to enter the same global transaction.

Applications that do not use the sessions facility must synchronize access to persistent data by all concurrent threads. In addition, such applications must synchronize threads before performing a commit, abort, or checkpoint operation in a global transaction.

Therefore, when one thread calls any of the following functions during a global transaction:

the user must ensure that no other thread in the same session is attempting to access persistent data.

Applications that use the sessions facility must synchronize access to persistent data by threads in the same session; ObjectStore synchronizes access to persistent data by threads in different sessions.

Note
You cannot use objectstore::set_thread_locking() to enable thread locking. This function is provided in Release 6.0 for backward compatibility, but calling it is in effect a no-op.

Local Transactions
ObjectStore synchronizes access to local transactions within the same session. For example, if thread 1 starts a local transaction, and thread 2 subsequently attempts to start a second transaction in the same session as thread 1, thread 2 will block until thread 1 either commits or aborts its transaction.

Locking Behavior in Nested Transactions

Previous to Release 6.0, all locks occurring during a nested transaction persisted until the outermost transaction finished. In this release, any locks occurring in a nested transaction that aborts are immediately released. This new behavior increases concurrency.

Existing applications that depend on transaction consistency across aborted nested transactions will have to be changed. (Applications should never depend on state that was read during any aborted transaction.)

Consider the following example:

start outer txn 
      start nested txn 
            read persistent var x 
      abort nested txn 
      start nested txn 
            read persistent var x 
      commit nested txn 
commit outer txn 
Previously, the two reads of x would see the same value. In Release 6.0, they are not guaranteed to see the same value -another client could change the value of x in the interval between the abort of the first nested transaction and the next read of x.

Abort-Only Transactions

ObjectStore no longer supports use of the abort_only enumerator to implement an abort-only transaction. This enumerator has been removed from the os_transaction API. User applications can implement an abort-only transaction by nesting an update transaction within a read-only transaction and rolling back the inner transaction with an explicit abort.

ObjectStore Fault Handler Macros

In Release 6.0, ObjectStore applications must use the fault handler macros OS_ESTABLISH_FAULT_HANDLER and OS_END_FAULT_HANDLER. In multithreaded applications, the macros must be used in every thread that can take page faults. A typical main function in an ObjectStore application would look like this:

int main (int argc, char** argv) { 
      OS_ESTABLISH_FAULT_HANDLER 
            // your code ... 
      OS_END_FAULT_HANDLER 
      return some_value; 
}
Braces and semicolons are not necessary; they are part of the macros. For more information about these macros, see the C++ API Reference, Chapter 4.

Notification Services

Closing a database discards all subscriptions within that database. You must reopen and resubscribe in order to continue receiving subscriptions.

Also, the notification API has been changed to support clusters. For more information, see

Functions and the const Qualifier

The const qualifier has been added or removed in the definitions of the following methods:

Methods taking const argument
Methods returning const value

Methods declared as const

Methods no longer declared as const

C Library Interface

As announced at Release 5.1, the C library interface is no longer supported and has been removed from Release 6.0 of ObjectStore.

ObjectStore Utilities

The following sections describe changes to utilities for managing ObjectStore tasks. For detailed information about all ObjectStore utilities, see Managing ObjectStore, Chapter 1, Overview of Managing ObjectStore and Chapter 4, Utilities.

oscmgr4

The oscmgr4 utility has been renamed to oscmgr6. For information about changes to the Cache Manager, see Cache Manager.

oscminit

The oscminit utility has been renamed to oscminit6. There is no change in behavior. This UNIX executable starts oscmgr6. The oscminit6 utility generally runs automatically to start the Cache Manager.

oscmstat

The Cache Manager status information displayed by the oscmstat utility has changed for Release 6.0. For each Server to which the Cache Manager is connected, oscmstat displays

For more detailed information about the format of oscmstat's output, see oscmstat: Displaying Cache Manager Status in Chapter 4 of Managing ObjectStore.

oscp

The oscp utility is not supported in Release 6.0 and is replaced by the oscopy utility. The oscopy utility makes a copy of an ObjectStore database. A key benefit of oscopy is that it performs transaction-consistent database copying without incurring locking conflicts.

oscopy cannot copy segment-level permissions and does not work with ObjectStore/Single. To copy an ObjectStore/Single database, use the copy command provided by your operating system.

osdump

The dump/load facility has changed in Release 6.0. Refer to the descriptions of osdump and osload in Managing ObjectStore. For information about using the dump/load facility to migrate a 5.1 database to Release 6.0, see Migrating a 5.1 Database to Release 6.0.

osprmgc

The osprmgc utility is not supported in Release 6.0. The problem it was devised to cure (PRM bloat) is no longer an issue; see Relocation Optimization. The os_dbutil::osprmgc() method is also not supported.

ossg

The following paragraphs describe to the neutralization options supported by the ossg utility.

New -arch options
The architecture sets named setn have been replaced with all, all32, and all64. The new sets contain all supported 32-bit and 64-bit platforms respectively.

Different names, same size
A new option, -portable_type_name, has been added to neutralize schemas in which different types names denote integral types of the same size on different platforms. For example, Solaris and SGI use long long to mean 64-bit integers, Visual C++ uses __int64, and other 64-bit platforms use long.

To correctly handle these differences, use the -portable_type_name option on the ossg command line and conditionally define a type to the correctly-sized type for each platform. The option can be abbreviated -ptn.

The syntax for this option is:

-portable_type_name name size 
name is the name of your type and size is the type's size in bytes.

The following example shows how to process a schema that uses a 64-bit integer called foo on Solaris and Windows platforms

  1. Add the following typedefs to your application code:

#if defined __OS_SOL2
typedef  long long foo
#else
typedef __int64 foo
#endif
  1. Then, add the following to your ossg command line:

-portable_type_name foo 8
wchar_t type
You can now neutralize a schema that includes the wchar_t type. Use the -wchar_t2 or -wchar_t4 option to specify to ossg whether a wchar_t should be two or four bytes.

osverifydb

The osverifydb utility has been changed to verify all segments, including internally managed ObjectStore segments. To verify a specific segment, use the new -segment_n option, which replaces the -n option. To skip internal segments, use the new -no_internal_segments option.

You can now verify a range of clusters in each segment, using the new -start_cluster and -end_cluster options. The -start_offset and-end_offset options have been changed to refer to offsets within clusters instead of segments.

The -info_sector_tag_verify_opt option has been removed.

For details about osverifydb, see osverifydb: Verifying Pointers and References in a Database in Chapter 4 of Managing ObjectStore.

Default Cache and Log files

ObjectStore/Single automatically creates default cache and log files. Previous releases required you to set the ObjectStore/Single environment variables OS_CACHE_FILE and OS_LOG_FILE and to call

objectstore::set_cache_file 
objectstore::set_log_file 
in order to create the files.

Both environment variables are still supported in Release 6.0; however, objectstore::set_cache_file has no effect on Windows platforms.

Managing ObjectStore Objects

Certain methods in the ObjectStore API return pointers to ObjectStore objects. These are transiently allocated objects that enable the user to call methods on such entities as a database or a transaction. Previous to this release, the lifetimes of these ObjectStore objects was managed by ObjectStore. Starting with Release 6.0, it is the user's responsibility to manage these objects.

The user should pay special attention to objects of the following classes:

For information about managing the lifetimes of ObjectStore objects, see C++ API User Guide. Release 6.0 of ObjectStore includes the release_pointer() and retain_pointer() methods for help in managing objects of the four classes; see, for example, os_cluster::release_pointer(). See also the following:

Note
Starting with Release 6.0, the delete operator has been defined for the four classes os_cluster, os_database, os_database_root, and os_segment. However, it should be used only when you know that the object to be deleted is not used anywhere else in the application. The release mechanism provides a safer approach to managing ObjectStore objects.

Obsolete Functions and Classes

The following member functions are obsolete and will be removed from the API in a later release. They are supported in Release 6.0 for compatibility only:

The following classes are obsolete and will be removed from the API in a later release. They are all part of the ObjectStore reference API. Their functionality has been replaced by soft pointers; see Soft Pointers. These classes are supported in Release 6.0 for compatibility only.

Note, however, that os_reference::get_open_database() has been removed from the API and is no longer supported.

Collections

Numerous changes have been made to the ObjectStore collections facility. This section describes those changes and provides information for upgrading your collections to Release 6.0. This section discusses the following topics:

For more information, see C++ Collections Guide and Reference.

Collections APIs Not Supported in Release 6.0

Classes
os_collection_size 
os_coll_rep_descriptor 
os_rDictionary 
os_rep 
os_rep_class 
os_rep_policy 
Enumerators
os_collection::maintain_cursors 
os_Collection::maintain_cursors 
os_collection::associate_policy 
os_collection::be_an_array 
os_collection::dont_associate_policy 
os_collection::dont_verify 
os_collection::safe 
os_collection::signal_cardinality 
os_collection::unsafe 
os_collection::verify 
Note
The enumerator os_collection::pick_from_empty_returns_null is supported for compatibility with previous releases but has no effect: a pick from an empty collection always returns null in Release 6.0.

Functions in supported classes
os_index_path::destroy() 
os_coll_query::destroy() 
os_collection::change_behavior() 
os_collection::change_rep() 
os_collection::get_rep() 
os_collection::get_thread_locking() 
os_collection::set_thread_locking() 
Macros
OS_MARK_RDICTIONARY()
OS_TRANSIENT_RDICTIONARY()
create() and destroy()
The create() and destroy() methods of the classes listed in Using new and delete with Collections are not supported.

New Collections APIs in Release 6.0

The following diagram shows the hierarchical relationship among the ObjectStore collection classes.

New classes
os_nlist and os_nList allow you to customize the os_list and os_List internal representations. These new classes replace the os_chained_list customization macros.

Using new and delete with Collections

In earlier versions of ObjectStore, the recommended way to create collections and collections subtypes, such as arrays and bags, was to call the os_collection::create() function. You did not use new to create collections. Likewise, the recommended way to destroy collections and its subtypes was to call the os_collection::destroy() function, and not use delete.

In Release 6.0, you create collections is with a constructor using new and destroy collections using delete. The constructors and destructors are for the following classes:

The create() and destroy() members of these classes are not supported.

Brief Compatibility with os_collection::create()

For compatibility with existing applications, the os_collection::create() function is supported in Release 6.0. This function will be removed from the next release of ObjectStore.

Component Schema Facility

Collections and query libraries now use the Component (DLL) Schema facility. If your application uses collections and query libraries, you no longer need to specify the ObjectStore library schema files (.ldb files) when you generate an application schema. Building your application with the libraries -loscol or -losqry (UNIX) or ostore.lib (Windows) will automatically load the corresponding component schema database (.adb file).

Controlling Representation Policy

In previous releases, you used AND and OR to specify the collection behavior you wanted. Based on your specifications, ObjectStore created a collection representation for you. In Release 6.0, each type of collection has certain behaviors associated with it. You cannot change which behaviors are associated with which type of collection. Consequently, you must use the collection type that has the behaviors you need, as shown in the following table.
Collections ClassMaintain Element OrderAllow DuplicatesSignal Duplicates
os_Set

No

No

No

os_Bag

No

Yes

No

os_List

Yes

Yes

No

os_Array

Yes

Yes

No

os_Dictionary, unordered

No

Yes

No

os_Dictionary, ordered

No

Yes

No

Cursor Behavior

There are no safe cursors in Release 6.0. For compatibility with earlier releases, you can use the Release 5.1 API to create a safe cursor, but it is not actually a safe cursor. Instead, ObjectStore creates an update-insensitive cursor.

Otherwise, cursor behavior and APIs in Release 6.0 are the same as cursor behavior and APIs in Release 5.1.

No Distinction Between Reference-Based and Pointer-Based Collections

In Release 5.1, some classes, provided reference-based collections. In Release 6.0, all collections behave like reference-based collections. There is no distinction between reference-based and pointer-based collections, because both are implemented using soft pointers; see Soft Pointers.

For example, in Release 5.1, you could use the os_vdyn_bag and os_vdyn_hash classes as ObjectStore collection representations. In Release 6.0, you should use os_bag or os_set instead.

os_rDictionary Not Supported

The os_rDictionary class has been removed from ObjectStore. It is replaced by the os_Dictionary class, which is now both reference-based and pointer-based. See No Distinction Between Reference-Based and Pointer-Based Collections.



[previous] [next]

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

Updated: 03/11/99 12:16:55