Chapter 18: Support Classes, Types, and Macros

 

Helper Types

Global helper types are available if you include the PObject header file.

 

o_1b

1-byte signed integer, a VERSANT number type that ensures portability.

 

o_2b

2-byte signed integer, a VERSANT number type that ensures portability.

 

o_4b

4-byte signed integer, a VERSANT number type that ensures portability.

 

o_8b

8-byte signed integer.

 

o_bcd

typedef struct o_bcd {

   char            sign;
   char            chart;
   unsigned char   dig[10];

}  o_bcd;

Store binary coded decimal floating point numbers with a precision of 18 digits in the range 10^-64 to 10^+63.

Parameters are:

sign

The sign. Specify POSITIV for a positive number or NEGATIV for a negative number.

chart

The exponent, expressed as a signed byte, in the range -64 to 63.

dig[10]

The eighteen mantissa digits, each in the range 0 through 9, packed two to a byte. The trailing digit is set to 00 when an object is loaded and ignored when an object is saved.

You can select on an attribute of type o_bcd, as the C/VERSANT o_predterm type and the C++/VERSANT PPredTerm and PBuffer classes now recognize the o_bcd type.

In a query, you can use the following comparison operators to compare o_bcd values:

                       C api      C++ operator

equal                  O_EQ       ==
not equal              O_NE       !=
less than              O_LT       <
less than or equal     O_LE       <=
greater than           O_GT       >
greater than or equal  O_GE       >=

On attributes of type o_bcd, you can create hash and b-tree indices.

There are no routines that operate on o_bcd or to convert them to and from other numeric types.

As with all VERSANT data types, o_bcd can be used across platforms and operating systems.

You must define arithmetic operators on o_bcd if you want to add, subtract, multiply, and divide. The recommended way to do this is to create an O_BCD C++ class that overloads the arithmetic operators. For example:

class O_BCD
{
   private:
      o_bcd data_member;
   public:
      friend O_BCD operator +(const O_BCD&, const O_BCD&);
      friend O_BCD operator -(const O_BCD&, const O_BCD&);
      friend O_BCD operator *(const O_BCD&, const O_BCD&);
      friend O_BCD operator /(const O_BCD&, const O_BCD&);
}

For example, the following class uses O_BCD:

class UserClass : public PObject {
   private:
      O_BCD my_balance; // bank account balance
   public:
      void a_method();
};

The following shows a query on UserClass::my_balance:

PAttribute mybal = "UserClass::my_balance.O_BCD::data_member";
O_BCD hundred_bucks = 100.0;
PPredicate pred = (mybal >= hundred_bucks.O_BCD::data_member);
PClassObject<UserClass>::Object().select(my_db,TRUE,pred);

In the above, notice it is necessary to know that the data member inside o_bcd is named Val, just as it is necessary to know the data member inside a VString is named s when you do a query on a VString that is embedded inside a defined class. Also, the .Val field must be named on the hundred_bucks object, so that the kernel type o_bcd is present in the predicate expression.

 

o_be_profile

struct o_be_profile
{
   /* creation parameters */
   o_u4b     be_sysvol_size;
   char*     be_sysvol_path;
   o_u4b     be_plogvol_size;
   char*     be_plogvol_path;
   o_u4b     be_llogvol_size;
   char*     be_llogvol_path;
   o_u4b     be_extent_size;

   /* starting parameters */
   o_bool    be_logging_enabled;
   o_bool    be_locking_enabled;
   o_bool    be_commit_flush;
   o_u4b     be_llog_buf_size;
   o_u4b     be_plog_buf_size;
   o_u4b     be_heap_size;
   o_u4b     be_max_page_buffs;
   o_u4b     be_lock_wait_timeout;
};

Data type used to manipulate database server process profiles.

See the Database Administration Manual for an explanation of each parameter.

 

o_bool

typedef o_u1b o_bool;

1-byte boolean type that is either TRUE or FALSE.

The Boolean type o_bool can be used as an attribute type. True and false are defined as follows.

TRUE

o_bool( 1 )

FALSE

o_bool( 0 )

 

o_clientconnectinfo

struct o_clientconnectinfo
{
  o_dbname cci_dbname;
} o_clientconnectinfo;

Name of a database that is connected in the current session. See o_clientconnectinfo().

 

o_clsname

typedef char* o_clsname;

Name of a class.

 

o_clsname_const

typedef const char* o_clsname_const;

Name of a class.

 

o_connectinfo

typedef struct o_connectinfo {

   o_u4b     ci_connection_id;
   o_u4b     ci_server_pid;

}  o_connectinfo;

This data type describes a database connection.

 

o_date

A signed 8 byte integer containing days since January 1, 1970.

The range 5,881,546 B.C. to year 5,885,486 is covered. Negative (2^31) (0x80000000) represents a null value.

You can create indexes and query on this type.

 

o_dblistdesc

typedef struct o_dblistdesc {

   o_dbname     dbname;
   o_4b         dbid;
   o_dbtype     dbtype;
   o_4b         dbgid;
   o_u1b        dbowner[O_NAME_SIZE];
   o_u1b        dbcreate[O_DATETIME_SIZE];
   o_u1b        dbversion[O_VERSION_SIZE];

} o_dblistdesc;

Data structure for the description of a database.

Elements:

dbname

Database name.

dbid

Database indentifier.

dbtype

Database type.

dbgid

Database group identifier.

dbowner

Database creator.

dbcreate

Database creation time stamp.

dbversion

Database version.

For dbtype, substitute one of the following:

O_DB_PERSONAL

Personal database.

O_DB_GROUP

Group database.

O_DB_UNIVERSAL

Public database.

 

o_dbname

typedef char o_dbname[length];

Name of a database optionally including a site name prefixed with the @ sign. The length is 286 bytes.

See also vpp_dbname.

 

o_dbname_const

typedef const char* o_dbname_const;

Name of a database optionally including a site name prefixed with the @ sign. The o_dbname_const datatype is defined as const char*.

 

o_double

8-byte floating point number, a VERSANT number type that ensures portability.

 

o_event_msg

struct o_event_msg{

    o_u4b   msg_len;
    o_uid   trid;
    o_u4b   dbid;
    o_u4b   event_seqno;
    loid    obj_event_defined;
    loid    obj_event_raised;
    o_u4b   event_type;
    o_4b    timestamp;
    o_u4b   definer_info_offset;
    o_u4b   definer_info_len;
    o_u4b   raiser_info_offset;
    o_u4b   raiser_info_len;
    loid    regid;
}   o_event_msg;

Store an event message.

The event message fields are:

msg_len

Size of the message in bytes.

The message length includes the size of the template o_event_msg and the size of information from the user who defined the event and the information from the user who raised the event. Therefore, an event daemon must allocate a buffer at least the size of msg_len to retrieve an event message.

trid

The transaction identifier of the transaction that raised the event.

dbid

The database identifer of the object.

event_seqno

A number that identifies and orders each event of a database in a transaction.

The sequence number is monotonically increased and managed by each server. If there are n events raised in a database, an application would receive n+2 events from the database. The first event is the system event, begin-event, with the sequence number 0. Then the n events follow with sequence numbers 1, 2, thru n. The last event is another system event, end-event, with sequence number n+1.

System events which monitor activities on objects may not be delivered in the same order as requests from an application that cause the activities, because the affected objects are cached in the application process of the application. When dirty objects are sent from the application object cache arrive to a server, their order becomes random for performance reasons.

Together, the trid, dbid, and event_seqno fields allow you to group and sort received events by database, transaction, and/or time received. This is useful, because a transaction may connect to and raise events from multiple databases, each of which manages its own events, and when a transaction is committed, you may receive event notifications from many databases.

obj_event_defined

The logical object identifier (loid) of the registered object on which the event is defined.

obj_event_raised

The logical object identifier (loid) of the object on which the event was raised.

The obj_event_defined and obj_event_raised fields may represent two different objects. For example, if obj_event_defined is a class object, the obj_event_raised might be an instance of that class. This might occur if obj_event_raised is the starting point for a query which raised an event message.

event_type

The event type.

timestamp

The time at which the event occurred.

For UNIX servers running on UNIX platforms, time is represented in a time_t data type which counts the number of seconds since 00:00:00 January 1, 1970, UTC (Coordinated Universal Time).

definer_info_offset

The offset to   information specified at event registration.

definer_info_len

The length of information specified at event registration.

An event message contains information from the definer which was supplied during the event registration. This information is represented by a pair (definer_info_offset and definer_info_len) specifying the offset and length, so that it can be forwarded easily across networks. To get the address of this information, use the macro O_EV_DEFINER_INFO(event_msg), where event_msg is a pointer to the event message received.

raiser_info_offset

The offset to the raiser supplied information.

raiser_info_len

The length of the raiser supplied information.

An event message contains information from the event raiser if the event was raised for a user event. This information is represented by a pair (raiser_info_offset and raiser_info_len) specifying the offset and length, so that it can be forwarded easily across networks. To get the address of this information, use the macro O_EV_RAISER_INFO(event_msg), where event_msg is a pointer to the event message received.

regid

The registration identifier.

Many of these fields are not meaningful for the system events begin-event and end-event.

For begin-event, the event_time field will contain the time when the first event was raised.

For end-event, the event_time field will contain the time when the originating transaction is committed.

For both begin-event and end-event, the fields obj_event_defined, obj_event_raised, definer_info_offset, definer_info_len, raiser_info_offset and raiser_info_len will contain null loids and zero-length strings. The zero-length strings will set their offsets to end of the message.

You do not have to register to receive begin-event and end-event: they are always sent when a transaction commits, from the databases serving the transaction.

 

o_envinfo

typedef struct o_envinfo {

   o_u1b     version[O_VERSION_SIZE];
   o_u1b     rootpath[O_PATH_SIZE];
   o_u1b     dbpath[O_PATH_SIZE];
   o_u1b     vrtpath[O_PATH_SIZE];

}  o_envinfo;

Data structure for database environmental data.

Elements:

version

Version number in display format.

rootpath

Installation root path.

dbpath

Database path.

vrtpath

VERSANT runtime path.

 

o_fe_alias

struct o_fe_alias {

   char*     alias_name;
   char*     alias_expansion; };

Data type used to manipulate database application process profiles.

See the Database Administration Manual for an explanation of each parameter.

 

o_fe_profile

struct o_fe_profile {

   o_u4b               fe_heap_size;
   o_u4b               fe_swap_threshold;
   o_u4b               fe_connection_count;
   char**              fe_connection_array;
   o_u4b               fe_alias_count;
   struct o_fe_alias*  fe_alias_array;

};

Data type used to manipulate database application process profiles.

See the Database Administration Manual for an explanation of each parameter.

 

o_float

4-byte floating point number, a VERSANT number type that ensures portability.

 

o_indextype

typedef enum o_indextype {

   O_IT_BTREE,
   O_IT_HASH

}  o_indextype;

A type of index.

Options are:

O_IT_BTREE

A btree index.

O_IT_HASH

A hash table index.

 

o_interval

A signed 8 byte integer containing nanoseconds.

An o_interval value is the result of subtracting an o_date value from another o_date value, an o_time value from another o_time value, or an o_timestamp value from another o_timestamp value.

An o_interval value can be added to an o_date, o_time, or o_timestamp value without changing the domain of the result. An o_interval value can be added to or subtracted from another o_interval value to produce another o_interval value.

You can create indexes and query on this type.

 

o_opts

typedef o_u4b o_opts[1];

A bit array of options. Options are explained in the context of individual commands.

 

o_time

A signed 8 byte integer containing the time of the day in milliseconds since midnight GMT (0:00:00.000).

The range 00:00:00.000 to 23:59:59.999 is covered. Negative (2^31) (0x80000000) represents a null value.

You can create indexes and query on this type.

 

o_timestamp

A signed 8 byte integer containing the nanoseconds before or after midnight January 1, 1970.

The range from 10-Jul-1677 00:00:00 and 0 nanoseconds to 21-May-2262 23:59:59 and 999999999 nanoseconds is covered (1.8 e+19 nanoseconds). Negative (2^63) (0x8000000000000000) represents a null value.

You can create indexes and query on this type.

 

o_u1b

1-byte unsigned integer, a VERSANT number type that ensures portability.

 

o_u2b

2-byte unsigned integer, a VERSANT number type that ensures portability.

 

o_u4b

4-byte unsigned integer, a VERSANT number type that ensures portability.

 

o_u8b

8-byte unsigned integer.

 

o_userdesc

typedef struct o_userdesc {

   o_u1b     username[O_NAME_SIZE];
   o_u1b     sitename[O_PATH_SIZE];
   o_4b      dbprivilege;
   o_4b      usertype;
   o_u1b     create[O_DATETIME_SIZE];

}  o_userdesc;

Data structure for a description of a database user.

Elements:

username[O_NAME_SIZE]

User name.

sitename[O_PATH_SIZE]

Site name.

dbprivilege

Database privilege.

usertype

User type.

create

Creation data and time.

For dbprivilege, substitute one of the following defined constants:

O_USR_READ

Read access.

O_USR_WRITE

Write access.

For usertype, substitute one of the following defined constants:

O_USR_IS_REGULAR

Regular user.

O_USR_IS_DBA

Dba user.

 

o_vsnstatus

typedef o_u4b o_vsnstatus;

A version type.

Options are:

VSN_TRANSIENT_VERSION

A transient version.

Transient versions are ordinary objects and can be updated or deleted at will. A transient version is usually a design under development. When stable, it can be promoted to a working version. Only a leaf version can be a transient version.

VSN_WORKING_VERSION

A working version.

A working version cannot be updated but can be deleted. Even when deleted the description of a working version persists in a version graph. A working version can be promoted to a released version.

VSN_RELEASED_VERSION

A released version.

A released version cannot be updated or deleted. It can be downgraded and then updated or deleted.

 

vpp_dbname

typedef char* vpp_dbname;

Name of a database optionally including a site name prefixed with the @ sign.

 

Directives

Directives can be used only in a schema implementation file.

 

O_CAPTURE_SCHEMA()

O_CAPTURE_SCHEMA(type);

Capture the class definition of a persistent class or template class.

You must write an O_CAPTURE_SCHEMA() directive for each class that will be stored in a database.

 

O_TRANSIENT()

O_TRANSIENT(class_name);

Declare attributes of type class_name to be transient.

O_TRANSIENT(class_name, "attribute1", "attribute2",....);

Declare the named attributes of the specified class to be transient.

A persistent capable class is a class that derives directly or indirectly from the PObject or PVirtual class. By default, the values of all attributes of a persistent capable class are stored in a database.

Declaring an attribute or class to be transient means that it will be transient:

•    in instances of the class
•    in instances of derived classes
•    in attributes of other classes when this class is used as an attribute type

In effect, this makes the class or attribute invisible to databases.

See the sections "Transient Attributes" and "Create and Load Schema Files" in the "Basic Programming" chapter of the C++/VERSANT Usage Manual.

 

Helper Macros

Global macros are available if you include the PObject header file.

 

AS()

AS( derivedClass, baseClassPtr );

Convert a type downward, return a pointer to a derived class derivedClass when given a pointer to a base class baseClassPtr, and throw an error if not successful.

The pointer to the base class baseClassPtr is cast to the specified type derivedClass if the pointer is to an instance of a superclass of the type, is of that type, or is convertible to a pointer to an instance of a superclass or that type. Otherwise an error is thrown.

Use AS() to convert downward if you have a pointer. You can also use AS() to cast a link downwards, but L_AS() is faster if you have a link.

Upward conversion is normally automatic. However, you must explicitly cast derived links upward to base links.

To use this macro on a transient object, you must have established run time type identification with a constructor macro. See "Class Constructors" in the Chapter "Creating Classes."

See also L_AS() and as().

The following code fragment illustrates a use of the AS() macro.

...
class Circle : public PObject {
private:
    o_double xCoordinate;
    o_double yCoordinate;
    o_double radius;
public:
    Circle(o_double, o_double, o_double);
    ...
};
...
class Arc : public Circle {
private:
    o_double angle;
public:
    Arc(o_double);
    ...
};
...
main()
{
    ...
    Circle* circlePointer =
        new Persistent Arc(20.0);
    PObject*   pOPointer      = circlePointer;
    Link<PObject> pOLink   = circlePointer;
    Link<Circle>  circleLink  = circlePointer;
    Arc*  arcPointer     = AS(Arc, circlePointer);
    Link<Arc> arcLink = AS(Arc, circlePointer);
    ...
}

In the above example, Arc is derived from Circle which is derived from PObject. The code first creates an instance of Arc as circlePointer.

If you need to convert circlePointer upward to PObject*, Link<PObject>, or a Link<Circle>, then you can just use a simple assignment statement.

If you need to convert circlePointer downward to either Arc* or Link<Arc>, then you must use AS() as shown.

 

assertClass()

void assertClass(

   const PObject&  obj,
   const PClass&   expect
   const char*     fname = NULL);

Assert that the given object obj is of the given class expect or derived from expect and raise an error if the assertion fails. You may provide the name of the function fname from which this is called, to be included in the error message.

To use this macro on a transient object, you must have established run time type identification with a constructor macro. See "Class Constructors" in the Chapter "Creating Classes."

 

assertSpecies()

void assertSpecies(

   const PObject&  obj,
   const PClass&   expect
   const char*     fname = NULL);

Assert that the given object obj is an instance of the given class expect and raise an error if the assertion fails.

If you provide the name of the function fname from which this method is called, the name will be included in the error message.

 

EOS

'\0'

End of string.

 

L_AS()

L_AS( derivedClassbaseClassLink );

Convert a type downward, return a pointer to a derived class derivedClass when given a link to a base class baseClassLink, and throw an error if not successful.

The link to the base class baseClassLink is cast to the specified type derivedClass if the link is to an instance of a superclass of the type, is of that type, or is convertible to a link to an instance of a superclass or that type. Otherwise an error is thrown. Using L_AS() to convert a link is faster than using AS().

Upward conversion for pointers is normally automatic. However, you must explicitly cast derived links upward to base links.

To use this macro on a transient object, you must have established run time type identification with a constructor macro. See "Class Constructors" in the Chapter "Creating Classes."

See also AS() and as().

The following code fragment illustrates a use of the L_AS() macro.

...
...
class Circle : public PObject
{
private:
    o_double xCoordinate;
    o_double yCoordinate;
    o_double radius;
public:
    Circle(o_double, o_double, o_double);
    ...
}
...
class Arc : public Circle
{
private:
    o_double angle;
public:
    Arc(o_double);
    ...
}
...
main()
{
    ...
    Link<Circle>  circleLink =
         new Persistent Arc(20.0);
    PObject*  pOPointer    = circleLink;
    Link<PObject> pOLink   = (PObject*)circleLink;
    Circle*  circlePointer = circleLink;
    Arc*  arcPointer    = L_AS(Arc, circleLink);
    Link<Arc> arcLink   =  L_AS(Arc, circleLink);
    ...

In the above example, Arc is derived from Circle which is derived from PObject. The code first creates an instance of Arc as circleLink. If you need to convert circleLink upward to PObject* or a Circle*, then you can just use a simple assignment statement. If you need to convert circleLink downward to either Arc* or Link<Arc>, then you must use L_AS() as shown.

 

NULL

#define NULL 0

You can use NULL to mean a null pointer. It is compatible with (char*).

 

NULL_LINK

Any variable of type Link<type> can be initialized by, assigned to, or compared with (using == or !=) NULL_LINK.

 

NULL_PREDICATE

You can use NULL_PREDICATE in query methods to select or checkout all instances of a class.

 

NULL_VSTR

Variables of type Vstr<type> or LinkVstr<type> can be compared with or set to NULL_VSTR.

For example:

LinkVstr<type> lv;
lv.set(NULL_VSTR);

 

O_NEW_PERSISTENT()

 

O_NEW_PERSISTENT1()

 

O_NEW_PERSISTENT2()

O_NEW_PERSISTENT( Type )( arguments );

Create a new persistent object of class Type in the default database and pass any values specified in arguments to the constructor for Type.

O_NEW_PERSISTENT( Template<Type> )( arguments );

Create a new persistent object of class Template<Type> in the default database and pass any values specified in arguments to the constructor for Type.

O_NEW_PERSISTENT1( dbType ) ( arguments );

Create a new persistent object of class Type in the specified database and pass any values specified in arguments to the constructor for Type.

O_NEW_PERSISTENT1( dbTemplate<Type> ) ( arguments );

Create a new persistent object of class Template<Type> in the specified database and pass any values specified in arguments to the constructor for Type.

O_NEW_PERSISTENT2( Template<Type1,Type2> )( arguments );

Create a new persistent object of class Template<Type1,Type2> and pass any values specified in arguments to the constructor for Template<Type1,Type2>.

Slightly different forms of the O_NEW_PERSISTENT() macro are required to create objects of normal classes, template classes with one type specifier, and template classes with two type specifiers.

The O_NEW_PERSISTENT1() macro will create the new object in a specified database.

The O_NEW_PERSISTENT() and O_NEW_PERSISTENT2() macros will create the new object in the default database. The default database is initially the session workspace specified when you begin a session. Once a session has been started, you can change the default database with set_default_db().

These macros will allocate space for the new object in the object cache, create a cached object descriptor for the object, pin the object in the object cache, and return a pointer to the new object.

For example, to create a new instance of the class Part, assuming that the Part constructor does not require any arguments:

Part* partPtr = O_NEW_PERSISTENT(Part);

Use new normally to create transient objects:

Part* partPtr = new Part;

For template classes with two arguments, such as VVVDictionary<A,B>, you must use the O_NEW_PERSISTENT2() macro or else the comma within the brackets in the template class name will be interpreted as an argument separater.

For example:

VVVDictionary<A,B>* ptr =
   O_NEW_PERSISTENT2(VVVDictionary<A,B>)(arg);

 

VPP_CLASS_CONSTRUCTOR1()

VPP_CLASS_CONSTRUCTOR1(type);

Constructor macro for non-template classes and template classes with one argument (including bilink, bilink vstr, and collection classes.)

A class constructor macro is required if you want to establish the type of a transient instance at run time or use a link to a transient object.

For example, the following methods require type identification:

Macros:

AS()              cast object
assertClass()     assert class derivation
assertSpecies()   assert class
L_AS()            cast object

PObject methods and macros:

as()              cast object
deleteobj()       delete object
is_a()            is instance of a class
is_instance_of()  is instance of a class

Link<type> methods:

as()              cast object
deleteobj()       delete object
is_instance_of()  is instance of a class

A class contructor macro must be the first statement in the constructor body.

Substitute the name of the class for the type parameter.

For example, for class A:

A::A()
{
   VPP_CLASS_CONSTRUCTOR1(A);
   ...
}

See also VPP_CLASS_CONSTRUCTOR2(), vppConstruct(), and the chapter "Creating Classes."

 

VPP_CLASS_CONSTRUCTOR2()

VPP_CLASS_CONSTRUCTOR2(type);

Constructor macro for template classes with two arguments.

A class constructor macro is required if you want to establish the type of a transient instance at run time or use a link to a transient object.

A class contructor macro must be the first statement in the constructor body.

Substitute the name of the class for the type parameter.

For example, for class A:

template < classB, classC >
A<B,C>::A()
{
   VPP_CLASS_CONSTRUCTOR2(A<B,C>);
   ...
}

See also VPP_CLASS_CONSTRUCTOR1(), vppConstruct(), and the chapter "Creating Classes."

 

vppConstruct()

vppConstruct(this);

Constructor macro for template classes with more than two arguments.

Constructor macro for template classes with two arguments.

A class constructor macro is required if you want to establish the type of a transient instance at run time or use a link to a transient object.

A class contructor macro must be the first statement in the constructor body.

Substitute the name of the class for the type parameter.

For example:

template <class X, class Y, class Z>
Object3<X,Y,Z>::Object3()
{
   PClassObject<Object3<X,Y,Z>>::Pointer() ->
   vppConstruct(this);
   .....
}

 

Lock Macros

Global lock macros are available if you include the PObject header file.

 

O_COMBINE_LOCK()

o_lockmode O_COMBINE_LOCK(

   EXTERNAL,
   INTERNAL,
   RESERVED );

Combine the external lock mode EXTERNAL and internal lock mode INTERNAL into a combined lock mode. The RESERVED parameter is reserved for future use; for this release, specify RESERVED as NULL.

For the EXTERNAL and INTERNAL parameters, you can specify any of the following:

WLOCK

Write lock.

RIWLOCK

Read/Intention-Write lock.

IWLOCK

Intention-Write lock.

ULOCK

Update lock.

RLOCK

Read lock.

IRLOCK

Intention-Read lock.

NOLOCK

No lock.

See o_lockmode for an explanation of these parameters.

In the upgradelock() and downgradelock() methods, if you do not want to change the value for just the external or internal parameter, you can specify O_LK_NO to indicate no change.

 

O_EXTERNAL_LOCK()

o_udllockmode O_EXTERNAL_LOCK( COMBINED );

Return the external lock mode from the combined lock mode COMBINED.

 

O_INTERNAL_LOCK()

o_udllockmode O_INTERNAL_LOCK( COMBINED );

Return the internal lock mode from the combined lock mode COMBINED.

 

O_IS_EXPLICIT_LOCK()

o_bool O_IS_EXPLICIT_LOCK( COMBINED );

Return TRUE if the combined lock is an explicit lock and otherwise return FALSE.

 

O_SET_EXPLICIT_LOCK()

Global macro

O_SET_EXPLICIT_LOCK( COMBINED );

Turn on the explicitness flag in the combined lock mode COMBINED.

 

Lock Types

Global lock types are available if you include the PObject header file.

 

Elemental lock types

 

o_lockmode

typedef o_u2b o_lockmode;

A single or combined lock mode used to specify a short lock.

You can specify either of two kinds of short locks in the o_lockmode data type:

External

An external lock provides concurrency among processes in separate sessions.

Combined

A combined lock provides concurrency both among processes in separate sessions and among processes within the same session.

External lock mode

Within a session with a single process, in methods that require a lock mode of type o_lockmode, you need only supply a single parameter that describes the desired type of lock. This single parameter will, by default, specify the external lock seen by other sessions.

Options for short lock parameters are:

WLOCK

Write lock.

A write lock prevents others from reading or updating the locked object.

If a write lock is placed on a class object, the effect is to write lock the both the class and all of its instances.

RIWLOCK

Read/Intention-Write lock.

A read/intention-write lock is only meaningful for a class object. It sets a read lock on instances of a class and sets an intention write lock on the class object. This prevents others from updating locked instances or reading or updating the class object.

IWLOCK

Intention-Write lock.

An intention-write lock is only meaningful for a class object. It prevents others from reading or updating a class object.

ULOCK

Update lock.

An update lock prevents others from updating the locked object and guarantee that you will be the next to get a write lock on the update locked object.

RLOCK

Read lock.

If on an instance, a read lock allows others to read the locked object but not update it.

If on a class object, a read lock allows others to read instances and the class object but not update instances or the class object.

IRLOCK

Intention-Read lock.

An intention-read lock is only meaningful for a class object. It allows others to read the class object but not update it.

NOLOCK

No lock. Also called a snapshot lock or a null lock.

A null lock provides no concurrency guarantees and allows others to read and update the object on which you have a null lock.

In the o_connectdb() method, the o_lockmode parameter is ignored even though it must be supplied for the method to work. When implemented, o_lockmode will not have the meanings described above. Rather, valid o_lockmode options will be limited to RLOCK, WLOCK, and NOLOCK and have the following meanings:

RLOCK

A read connection mode that allows you to view but not change data.

WLOCK

A write connection mode that allows you to view and edit data.

NOLOCK

A connection mode that does not allow you to lock objects.

No locks are placed on the objects returned by a query. To access and place a read lock on an object in the vstr returned by a query, you can dereference an object in the returned LinkVstr<type> with operator ->, type*, or PObject*. Alternately, you can access an object and explicitly specify a lock with the locateobj() method in Link<type> and LinkAny.

The default lock mode when objects are read is a read lock. To change the default, use the set_default_lock() method.

For example, to change the default to a write lock:

dom -> set_default_lock(WLOCK);

In query methods, the o_lockmode option applies to the class object only. Thus, to avoid unintentioned side effects, you should normally only specify one of the following in select(): IRLOCK, an intention read lock; IWLOCK, an intention write lock; NOLOCK, no lock. Sometimes, however, you will want to set a read or write lock on a class object when performing a query. Thus, all o_lockmode parameters can be used in query methods.

Combined lock modes

In shared sessions there may be multiple processes accessing the same object cache in shared memory. Accordingly, locks must provide concurrency among processes in the same session as well as among processes in separate sessions. To provide this concurrency, in methods that require a lock mode, you can either specify just an external parameter, such as RLOCK, or you can provide finer grain control by specifying a combined lock mode.

A combined lock mode specification consists of three parts:

External lock mode

External locks provide concurrency with activities and transactions that are not related by an ancestor or descendant relationship, such as a transaction or activity in another application or an activity in the same session that is running with another process and that is in a separate stack of activities.

For an external lock request to be granted, the external lock mode must be compatible with external short locks placed by other activities that are not related by an ancestor or descendant relationship and with internal locks placed by ancestor activities.

For example, you cannot set an external read lock on an object if another process has an external write lock on that object. Also, you cannot set an external write lock in an activity if a parent activity has an internal read lock.

Depending upon your specifications in the "end activity" method, external locks can be inherited by parent activities when an activity ends.

Internal lock mode

Internal locks provide concurrency with ancestor activities.

For a lock request to be granted, the internal lock mode must be compatible with external locks held by descendant activities.

For example, you cannot set an internal write lock in a parent activity if a child has an external read lock.

Internal locks are not inherited when an activity ends.

Explicitness

Explicit locks are used for excluding changes from rollbacks.

Changes to an object with an explicit lock will be excluded from rollback if the changes have been previously written to a database with the "write explicit" method.

In nested activity sessions, even though there is only one process in the session, you may want to supply a combined lock mode in order to use the explicitness parameter to exclude certain changes from rollback.

For coding compatibility, you can also supply a combined lock mode in standard sessions, but in those cases only the external lock mode will be used.

Combined lock modes are specified using the O_COMBINE_LOCK() macro. See O_COMBINE_LOCK() for more information.

 

o_udllockmode

typedef o_1b o_udllockmode;

External or internal lock mode component of a combined lock mode.

Used in the O_EXTERNAL_LOCK() and O_INTERNAL_LOCK() macros.

 

PLock

Instances of PLock can be used to describe persistent locks. The PLock class is available if you include the PObject header file.

 

PLock()

PLock();

PLock(

   o_plmode  mode,
   o_pllevel level,
   o_plqopt  qopt,
   o_u2b     intent,
   o_u2b     events );

Create an instance of PLock that describes a persistent lock.

The default is to set a read lock with a soft level that pauses until the lock is ready or the request is timed out and that does not notify you of locking events related to that object.

The PLock data type is used in acquireplock(), gcheckout(), pcheckout(), and checkin(). You cannot use a NULL pointer for a lock description in a predicate checkout pcheckout().

See also the VERSANT Database Fundamentals Manual for a complete explanation of locking options. Following is a brief description of options.

Options for mode are:

O_PL_READ

Read lock.

O_PL_WRITE

Write lock.

O_PL_SNAPSHOT,
O_PL_NOLOCK

Null lock.

These options are mutually exclusive.

Options for level are:

O_PL_HARD

Hard level that cannot be broken.

O_PL_SOFT

Soft lock that can be broken.

These options are mutually exclusive.

If an object is not immediately available for locking, your queuing option qopt determines what happens next. Options for qopt are:

O_PL_WAIT

VERSANT will keep trying to obtain the persistent lock until the request times out.

If the object is not available after the request times out, then the error message OM_LO_BE_INCOMPAT will be returned, which must be caught.

The length of the time-out period is determined by the value of the server process parameter lock_wait_timeout in the database server profile file profile.be.

O_PL_RESERVE

VERSANT will immediately return the error message OM_LO_BE_INCOMPAT, which must be caught, and then place a persistent lock reservation on the object. When the object is available, notification will be sent by electronic mail.

O_PL_NO_BLOCK

VERSANT will immediately return the error message OM_LO_BE_INCOMPAT, which must be caught, and make no further attempts to acquire the persistent lock.

These options are mutually exclusive.

The intent parameter is reserved for future use; for the present release specify 0.

Options for events are:

O_PL_LOCK_BROKEN

Send a message if your soft lock is broken by another user.

O_PL_REQ_PENDING

Send a message if someone else is waiting for your lock.

O_PL_OBJ_READY

Send a message when your object is ready.

Notifications are sent in the form of electronic mail. The system will evaluate your outstanding message requests each time a short transaction commits or rolls back. You can also monitor objects for object related events by using o_monitorobj().

These options can be combined with the "or" operator |.

For example, to set persistent, soft, write locks on a group of objects partsToLock using acquireplock():

LinkVstr<Part> partsToLock = ...

PLock LockType(
   O_PL_WRITE, // Lock Mode
   O_PL_SOFT,  // Lock Level
   O_PL_WAIT,  // Queuing option
   0, // Intent option
   0 );  // Events mask

dom->acquireplock(partsToLock, LockType);

 

Error Support

 

Error Functions

Global error functions are available if you include the PObject header file.

 

rethrow

rethrow;

Throw an error from a catch block to the next outermost pair of try and catch blocks.

 

set_panic()

VPP_PANIC_HANDLE set_panic( VPP_PANIC_HANDLE panic_function );

Set the function called when an unrecoverable error occurs to the function panic_function.

When VERSANT encounters an unrecoverable error, it calls a panic function to print a message and the place of the error. The default kernel panic function will then abort the application and exit with a rollback.

You might want to change the default panic function to vpp_panic(), which uses normal C++ exception handling mechanisms to throw a PError object with the description and location of the unrecoverable error.

To set the panic function to vpp_panic(), include <cxxcls/pobject.h> and call set_panic() as follows:

#include <cxxcls/pobject.h>
main()
{
   set_panic(vpp_panic);
   ...
}

The set_panic() function will return a pointer to the old panic function.

You can replace vpp_panic() with your own panic handling function which could give a customized error message, but you should not try to use any VERSANT function. A panic function should abort at the end.

For example:

#include <cxxcls/pobject.h>
void my_panic_handler(
   const char* msg,
   o_4b  line_num,
   const char* file_name);
{
   // output:
   // panic case: msg
   // panic at line line_num of file file_name
   exit(1);
}
int main()
{
   set_panic(my_panic_handler);
   ...
}

 

set_terminate()

void set_terminate( VPP_PFV function_ptr );

Reset the behavior of the terminate() function by specifying a pointer to an alternate function that you have defined.

 

set_unexpected()

void set_unexpected( VPP_PFV function_ptr );

Reset the behavior of the unexpected() function by specifying a pointer to an alternate function that you have defined.

 

terminate()

extern void terminate();

The default behavior of VERSANT's built-in terminate() function is:

1.  Print the word "terminating" on stderr.

2.  If the global variable vpp_terminate_where is not NULL, then print the character string it contains.

3.  If the global variable vpp_terminate_why is not NULL, then print the character string it contains.

4.  Call o_exit(1), which terminates the application process with a rollback. This is the same as calling dom->exit(1).

See also unexpected(), set_unexpected(), and set_terminate().

 

unexpected()

extern void unexpected();

The unexpected() function is automatically invoked if an error is thrown but not caught. This happens if there is no enclosing try block or if all catch blocks rethrow the error.

The default behavior of VERSANT's built-in unexpected() function is:

1.  Print "Unexpected exception:" on stderr.

2.  Print the description() of the unexpected error.

3.  Call terminate(). See also terminate().

 

vpp_break()

extern "C" void vpp_break();

When errors are raised, the terminate(), unexpected(), and throw() error handling functions internally call the vpp_break() subroutine. You can put a breakpoint on vpp_break() so that your debugger gains control when an error occurs.

 

vpp_panic()

void vpp_panic(
   const char*   err_desc,
   o_4b          line_number,
   const char*   file_name );

When an unrecoverable error occurs, the function vpp_panic() uses C++ exception handling mechanisms to throw an object of type PError with a description and the place of the unrecoverable error and then calls exit(1) which exits with a rollback.

To use vpp_panic, you must include <cxxcls/pobject.h> and <cxxcls/perror.h>.

The vpp_panic() function is the recommended panic handler function for C++/VERSANT. See set_panic() for how to change the default handler

The output of vpp_panic() could be:

•    When the error number is found in the error message file, the output is something like:

VSL_BLKNO_INVAL:  Invalid block number  (main.cxx:23)

•    When the error number cannot be found in the error message file, the output is something like:

<< 100000 >>   (main.cxx:23)

•    In very rare cases, vpp_panic() could be called twice and it will output:

object manager panics twice

 

Error Macros

Global error macros are available if you include the PObject header file.

 

__HERE__

#define __HERE__  __FILE__,__LINE__

The standard C preprocessor, used in C++ as well, understands the special macros __FILE__ and __LINE__, which expand into the filename and the line number of the source file in which they appear. The __HERE__ macro combines these two so that you can inform a PError object where in the source it was created.

For example:

throw(PError(WIDGET_NOT_FOUND,__HERE__));

 

vpp_thread_terminate()

void vpp_thread_terminate()

In a thread session, replace the default error handling method vpp_terminate().

The vpp_thread_terminate() macro will do the following.

1.  Print the word "terminating" on stderr.

2.  Print the error message in the latest exception (PError::print()).

3.  Call thread exit to exit the thread.

 

vpp_thread_unexpected()

void vpp_thread_unexpected()

In a thread session, replace the default error handling method vpp_unexpected().

The vpp_thread_unexpected() macro will do the following.

1.  Print the words "Unexpected exception" on stderr.

2.  call vpp_thread_terminate().

 

Error Types

Global error types are available if you include the PObject header file.

 

kind

typedef d_Long kind;

Included for ODMG compatibility.

 

o_err

typedef o_4b o_err;

A VERSANT error code number.

 

o_error

typedef struct o_error {

   o_err     e_errno;
   o_u4b     e_oserr;

} o_error;

An error.

Elements:

e_errno

VERSANT error code number.

e_oserr

Operating system related error.

 

Error Variables

Global error variables are available if you include the PObject header file.

 

VPP_PANIC_HANDLE

typedef void( *VPP_PANIC_HANDLE )(

   const char*   error_desc,
   o_4b          line_number,
   const char*   file_name );

A pointer to a function to be used as a panic handler, where error_desc is a character string that describes the error, line_number is the line number where the error occurred, and file_name is the name of the file in which the error occurred.

See also vpp_panic() and set_panic().

 

VPP_PFV

typedef void ( *VPP_PFV )();

As defined in C++, this is the type of a pointer to a function that takes no argument. It is used as the data type of the argument for and returned value of set_terminate() and set_unexpected().

 

vpp_terminate_where

const char* vpp_terminate_where = NULL;

•    Before calling terminate(), VERSANT will set vpp_terminate_why to one of the following:

"No memory (cannot malloc)"

This means that a call to malloc or operator new() failed. You are probably out of swap space.

"PError thrown while throwing PError"

An error has occurred during the error handling process.

"too many nested try blocks"

The Check Facility terminates if there are more nested try blocks than the value specified in VppTryDepthMax. See also VppTryDepthMax.

•    If you set the global variable vpp_terminate_why to a character string rather than NULL, the contents will be printed whenever the VERSANT default terminate() method is invoked. See also terminate().

 

vpp_terminate_why

const char* vpp_terminate_why = NULL;

Print error when terminate() is invoked.

If the global variable vpp_terminate_why is a character string rather than NULL, the contents will be printed whenever the VERSANT default terminate() method is invoked. See also terminate().

 

PError

The PError class is available if you include the PObject header file.

For a standard installation, error messages are stored in the files:

VERSANT_RELEASE_DIRECTORY/lib/error.msg

VERSANT_RELEASE_DIRECTORY/lib/error.txt

You can define your own error by allocating an error number greater than 50,000, using the constructor to create your own error, adding you error message to the error.msg file, and using methods defined on PError.

Including <cxxcls/pobject.h> provides access to all error handling methods.

 

PError()

PError();

Construct an empty instance of PError.

PError( o_err err_num );

Construct an instance of PError and specify an error handle as err_num.

PError( o_err n, char* file, o_u4b     line );

Form for PError(num, __HERE__) usage.

 

~PError()

~PError();

Destructor.

 

<<()

PError& operator << ( o_1b        value );
PError& operator << ( o_u1b       value );
PError& operator << ( o_2b        value );
PError& operator << ( o_u2b       value );
PError& operator << ( o_4b        value );
PError& operator << ( o_u4b       value );
PError& operator << ( o_8b        value );
PError& operator << ( o_u8b       value );
PError& operator << ( o_double    value );
PError& operator << ( const char* value );

Supply a value for %d, %s, or %f when used in an error description string.

For example, you might create an error 15001, named APP_NOTHING_FOUND. The error description string in error.msg might be:

15001, No objects of class %s were found

In the case of the above line, you could then use the << operator to supply a value for %s in the error description string.

For example:

PError e(APP_NOTHING_FOUND);
throw (e << "Employee");

Example

This example has been simplified so that PError handles only a few, specific error numbers. Although this example does not show it, try blocks can be nested.

#include <libc.h>
#include "employee.h"
#include "departme.h"
main
{
   const lineSize = 1024;
   char predicate[lineSize];
   char value[lineSize];
   char response[lineSize];
   #define APP_NOTHING_FOUND 50001;
   dom = new PDOM;
   dom-> beginsession("myDatabase");
   do
   {
      try
      {
         cout << "Enter predicate: ";
         cin.getline(predicate,linesize)
         cout << "Enter value: ";
         cin.getline(value, linesize)
         LinkVstr<Employee> staff =
            PClassObj<Employee>.select(
               "myDatabase,"
               TRUE,
               IRLOCK,
               predicate,
               value);

         if (staff.empty())
         {
            PError e(APP_NOTHING_FOUND);
            throw (e << "Employee");
         }

         Employee* worker = staff[0];

         staff.release();

         cout  << "Found: "
               << (char*)(worker->getName())
               << endl;
      }
      catch (PError& err)
      {
         switch (err.errnum)
         {
            case CXX_NO_SUCH_ATTR:
            case CXX_BAD_PRED:
            case APP_NOTHING_FOUND:
               err.print();
               break;
            default: rethrow;
         }
      }
      cout  << "Continue ? ";
   }
   while (
      cin.getline(response,lineSize) &&
         (response[0] == 'y' || response[0] == 'Y');
      cout  << "Commit the short transaction and exit..."
            << endl;
      dom -> exit(0);
}

For a standard installation, error messages are stored in the file:

/usr/local/osc/lib/error.msg

The line for error 50001, named APP_NOTHING_FOUND in the C++ source code, might be:

50001, No objects of class %s were found

In the case of the above line, the string "Employee" was supplied by the throw for substitution for the %s in the error description string.

 

createerror()

static void createerror(o_error* errStack);

Create a new error stack which is initially empty. The error stack can later be used to hold application errors.

See also: deleteerror(), deleteerrortext(), formaterrortext(), getcurrenterror(), pusherrorstack(), seterrorparam().

 

description()

void description(

   char*     buf,
   o_u4b     bufsize );

Write an error description for this object into the given buffer. The maximum size of the buffer must be provided. The values supplied by the throw with operator << are substituted into the % codes in the error description string.

 

deleteerror()

static void deleteerror(o_error errStack);

Delete memory used by an o_error structure when the o_error structure is no longer required.

See also: createerror(), deleteerrortext(), formaterrortext(), getcurrenterror(), pusherrorstack(), seterrorparam().

 

deleteerrortext()

static void deleteerrortext(char* text);

Delete the memory associated with the error text allocated by the formaterrortext() function.

See also: createerror(), deleteerror(), formaterrortext(), getcurrenterror(), pusherrorstack(), seterrorparam().

 

get_error_number()

o_err get_error_number();

Return the error number in this instance of PError.

 

get_file_name()

char* get_file_name();

Return the file name where an error was thrown, if you have used the PError(n,file,line) constructor; otherwise, return NULL.

 

get_kind()

kind get_kind();

Included for ODMG compatibility.

 

get_line_number()

o_u4b get_line_number();

Return the line number in the file where an error was thrown, if you have used the PError(n,file,link) constructor; otherwise, return NULL.

 

getcurrenterror()

static void getcurrenterror(o_error* errStack);

Get a description of the error generated by the last VERSANT Manager function call and return it to the new instance of o_error specified as errStack.

See also: createerror(), deleteerror(), deleteerrortext(), formaterrortext(), pusherrorstack(), seterrorparam().

 

print()

void print(

   FILE*     f = stderr,
   o_bool    usePrefix = TRUE );

Call the description() method and print the result followed by a new line to the specified file. The default file is the standard error file.

 

pusherrorstack()

static void pusherrorstack(

o_error errStack,
o_err   err,
char*   file,
o_u4b   line );

Add a new error to the stack, initializing from the value of err that has been retrieved by getcurrenterror() or created by createerror().

See also: createerror(), deleteerror(), deleteerrortext(), formaterrortext(), getcurrenterror(), seterrorparam().

 

seterrorparam()

static void seterrorparam(

o_error      errStack,
const char*  param,
const char*  value);

Set the value of a parameter for the topmost level of the specified error.

If the parameter is already set, this function will overwrite the old value. If the parameter does not exist, the function will append the parameter to the list.

You can use the sourcefile and sourceline parameters to specify the source file and line number where an error occured.

See also: createerror(), deleteerror(), deleteerrortext(), formaterrortext(), getcurrenterror(), pusherrorstack().

 

set_kind()

void set_kind(kind error_code);

Included for ODMG compatibility.

 

PResult

The PResult class is available if you include the PObject header file.

 

PResult()

PResult();

The constructor takes no arguments and initializes the internal state to O_OK.

 

clear()

void clear();

Assign the state of this instance of PResult to O_OK. Methods that take PResult& as an argument should either use set() or clear() on the PResult& before returning.

 

get_error_number()

o_err get_error_number() const;

Return the state of this instance of PResult which will be an error code if an error has occurred or O_OK if there has been no error.

 

is_bad()

o_bool is_bad() const;

Return TRUE if the internal state of this instance of PResult is not O_OK and otherwise return FALSE.

 

is_ok()

o_bool is_ok() const;

Return TRUE if the internal state of this instance of PResult is O_OK and otherwise return FALSE.

 

set()

void set( o_err e =::o_errno );

Assign the state of this instance of PResult to a specified error code e or, by default, to the value of the global variable o_errno. Methods that take PResult& as an argument should either use set() or clear() on the PResult& before returning.

 

Comparison and Activation Classes

 

PVirtual

Class PVirtual contains comparison, initialization, and activation methods.

 

Comparison methods

The PVirtual class is an abstract class which defines virtual methods for hashing and comparison.

If you want to perform value comparisons, you must derive the elements from PVirtual and define for them a comparison method compare() and a hashing method hash().

Class PVirtual inherits from PObject, so you do not have to include PObject in your list of base classes if you derive your class from PVirtual. However, if you do not include pobject.h, you must include <cxxcls/vcommon.h>.

The PVirtual class defines two virtual methods: hash() and compare(). These methods must be redefined by derived classes, because there is no way to know what attributes you want to use to make the comparison or how to compare the attributes.

See also the usage notes in the "Collection Classes" chapter of the C++/VERSANT Usage Manual.

 

=()

operator=(const PVirtual& pv);

Set this instance of PVirtual equal to specified object.

 

compare()

virtual o_4b compare( const PVirtual& other_obj ) const;

Compare this object with another object specified as other_obj.

The compare() method should be redefined by a derived class so that a negative number is returned if this object is "less than" the other object, zero if this object is "equal to" the other object, and a positive number if this object is "greater than" the other object.

For example, to compare coordinates by considering first the x and then the y coordinates:

class Coord : PVirtual
{  public:
   ...
   o_4b compare( const PVirtual* c ) const
   {  if ( x == c.h && y == c.y ) return 0;
      if ( y == c.y ) return x - c.x;
      return y - c.y;
   }
}

Following are comparison operators on PVirtual.

!=

o_bool operator!=(const PVirtual& other) const;

Not equal.

<

o_bool operator<(const PVirtual& other) const;

Less than.

<=

o_bool operator<=(const PVirtual& other) const;

Less than or equal to.

==

o_bool operator==(const PVirtual& other) const;

Equal.

>

o_bool operator>(const PVirtual& other) const;

Greater than.

>=

o_bool operator>=(const PVirtual& other) const;

Greater than or equal to.

 

hash()

virtual o_u4b hash() const;

Map an object to an unsigned integer.

The hash() method should be redefined by a derived class so that if two objects are equal, their hash value is the same.

 

Initialization method

 

init()

void init();

Fix this C++ object when first brought into memory.

To initialize an object with transient data when it is brought into memory, derive its class from PVirtual and then redefine the init() method. The init() method will be called after the C++ activation.

By default, init() is not called when objects are brought into memory. To cause it to be called, use set_call_user_init_flag() in PCustomizeFundamental.

See set_call_user_init_flag() in PCustomizeFundamental for usage notes.

 

Activation and deactivation methods

You can activate and deactivate objects from classes that inherit directly or indirectly from PVirtual. This allows you to control actions performed when an object enters or leaves the object cache.

Activation and deactivation functionality are provided by the virtual methods d_activate() and d_deactivate().

Classes that derive from PVirtual are checked to see if they provide an implementation of d_activate() and d_deactivate(). If a class or any of its base classes derived from PVirtual do not override the default implementation of d_activate() and d_deactivate(), nothing happens when an object is activated or deactivated.

If a class or any of its base classes derived from PVirtual does implement d_activate(), then it will be called when an instance enters the object cache. If there is an implementation of d_deactivate(), it will be called when an instance leaves the object cache.

 

d_activate()

virtual void d_activate();

If implemented on a class directly or indirectly deriving from PVirtual, activate an instance of the class when it enters the application object cache.

 

d_deactivate()

virtual void d_deactivate();

If implemented on a class directly or indirectly deriving from PVirtual, deactivate an instance of the class when it leaves the application object cache.

 

d_Object methods

void mark_modified();

Mark this object as dirty.

The ODMG d_Object class is aliased to PVirtual.

 

VElemental

 

Overview

The VElemental class is an abstract class which implements hashing and comparison methods for elemental data types, links, pointers, references, and vstrs of elemental types or links.

To declare and use VElemental, just include the file for the collection class involved. This will also include vcommon.h and velement.h.

The hashing and comparison methods in VElemental are defined on many types:

•    Elemental types, including o_1b, o_u1b, o_2b, o_u2b, o_4b, o_u4b, o_float, o_double.

•    Links, pointers, and references to objects of class PObject and PVirtual.

•    Vstrs of elemental types.

•    Link vstrs of PObject or PVirtual.

The class VElemental defines a number of methods on elemental types. This class contains no data, so all of the methods are static.

 

compare()

o_u4b compare( first_instance, second_instance );

The overloaded VElemental::compare() method compares two instances of a given type.

In the case of a numeric type, the comparison method is a simple inline function. The value returned is -1, 0, or 1 depending upon whether the first instance is considered, respectively, to be less than, equal to, or greater than the second instance.

 

hash()

o_u4b hash( instance );

The overloaded VElemental::hash() method performs hashing on an instance of a given type.

The functions defined by these methods are designed to provide good mixing properties and also to be fairly efficient.

 

combine()

o_u4b combine( o_u4b hash_1, o_u4b hash_2 );

Combine two or more hash values together into a new hash value.

For your convenience, up to eight hash value arguments may be supplied.

 

 

 


This online documentation is confidential and proprietary to Versant Corporation and is licensed to you, or to your organization, pursuant to the terms of an agreement between you and Versant that restricts the use of this documentation. Please refer to the agreement for more information or call Versant at 510-789-1500 with any questions.