PObject
header file.
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
POSITIV
for a positive number or NEGATIV
for a negative number.
chart
-64
to 63
.
dig[10]
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.
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.
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.
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 )
struct o_clientconnectinfo
{
o_dbname cci_dbname;
} o_clientconnectinfo;
Name of a database that is connected in the current session. See o_clientconnectinfo()
.
typedef char* o_clsname;
Name of a class.
typedef const char* o_clsname_const;
Name of a class.
typedef struct o_connectinfo {
o_u4b ci_connection_id;
o_u4b ci_server_pid;
} o_connectinfo;
This data type describes a database connection.
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.
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
dbid
dbtype
dbgid
dbowner
dbcreate
dbversion
dbtype
, substitute one of the following:
O_DB_PERSONAL
O_DB_GROUP
O_DB_UNIVERSAL
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
.
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*
.
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
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
dbid
event_seqno
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
loid
) of the registered object on which the event is defined.
obj_event_raised
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
timestamp
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
definer_info_len
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
raiser_info_len
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
begin-event
and end-event
.
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.
begin-event
and end-event
: they are always sent when a transaction commits, from the databases serving the transaction.
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
rootpath
dbpath
vrtpath
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.
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.
typedef enum o_indextype {
O_IT_BTREE,
O_IT_HASH
} o_indextype;
A type of index.
Options are:
O_IT_BTREE
O_IT_HASH
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.
typedef o_u4b o_opts[1];
A bit array of options. Options are explained in the context of individual commands.
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.
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.
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]
sitename[O_PATH_SIZE]
dbprivilege
usertype
create
dbprivilege
, substitute one of the following defined constants:
O_USR_READ
O_USR_WRITE
usertype
, substitute one of the following defined constants:
O_USR_IS_REGULAR
O_USR_IS_DBA
typedef o_u4b o_vsnstatus;
A version type.
Options are:
VSN_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 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 cannot be updated or deleted. It can be downgraded and then updated or deleted.
typedef char* vpp_dbname;
Name of a database optionally including a site name prefixed with the @
sign.
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(class_name);
class_name
to be transient.
O_TRANSIENT(class_name, "attribute1", "attribute2",....);
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.
PObject
header file.
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.
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."
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.
'\0'
End of string.
L_AS( derivedClass, baseClassLink );
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.
#define NULL 0
You can use NULL
to mean a null pointer. It is compatible with (char*)
.
Link<type>
can be initialized by, assigned to, or compared with (using ==
or !=
) NULL_LINK
.
NULL_PREDICATE
in query methods to select or checkout all instances of a class.
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( Type )( arguments );
Type
in the default database and pass any values specified in arguments
to the constructor for Type
.
O_NEW_PERSISTENT( Template<Type> )( arguments );
Template<Type>
in the default database and pass any values specified in arguments
to the constructor for Type
.
O_NEW_PERSISTENT1( db, Type ) ( arguments );
Type
in the specified database and pass any values specified in arguments
to the constructor for Type
.
O_NEW_PERSISTENT1( db, Template<Type> ) ( arguments );
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 );
Template<Type1,Type2>
and pass any values specified in arguments
to the constructor for Template<Type1,Type2>
.
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(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 objectassertClass()
assert class derivationassertSpecies()
assert classL_AS()
cast object
PObject
methods and macros:
as()
cast objectdeleteobj()
delete objectis_a()
is instance of a classis_instance_of()
is instance of a class
as()
cast objectdeleteobj()
delete objectis_instance_of()
is instance of a class
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(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(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);
.....
}
PObject
header file.
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
RIWLOCK
IWLOCK
ULOCK
RLOCK
IRLOCK
NOLOCK
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_udllockmode O_EXTERNAL_LOCK( COMBINED );
Return the external lock mode from the combined lock mode COMBINED
.
o_udllockmode O_INTERNAL_LOCK( COMBINED );
Return the internal lock mode from the combined lock mode COMBINED
.
o_bool O_IS_EXPLICIT_LOCK( COMBINED );
Return TRUE
if the combined lock is an explicit lock and otherwise return FALSE
.
Global macro
O_SET_EXPLICIT_LOCK( COMBINED );
Turn on the explicitness flag in the combined lock mode COMBINED.
PObject
header file.
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
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
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
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
An intention-write lock is only meaningful for a class object. It prevents others from reading or updating a class object.
ULOCK
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
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
An intention-read lock is only meaningful for a class object. It allows others to read the class object but not update it.
NOLOCK
A null lock provides no concurrency guarantees and allows others to read and update the object on which you have a null lock.
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
WLOCK
NOLOCK
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
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.
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.
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.
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.
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
can be used to describe persistent locks. The PLock
class is available if you include the PObject
header file.
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
O_PL_WRITE
O_PL_SNAPSHOT,
O_PL_NOLOCK
Options for level
are:
O_PL_HARD
O_PL_SOFT
If an object is not immediately available for locking, your queuing option qopt
determines what happens next. Options for qopt
are:
O_PL_WAIT
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
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
OM_LO_BE_INCOMPAT
, which must be caught, and make no further attempts to acquire the persistent lock.
The intent
parameter is reserved for future use; for the present release specify 0
.
Options for events
are:
O_PL_LOCK_BROKEN
O_PL_REQ_PENDING
O_PL_OBJ_READY
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);
PObject
header file.
rethrow;
Throw an error from a catch block to the next outermost pair of try and catch blocks.
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);
...
}
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.
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.
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()
.
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()
.
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.
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)
<< 100000 >> (main.cxx:23)
vpp_panic()
could be called twice and it will output:
object manager panics twice
PObject
header file.
#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__));
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.
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()
.
PObject
header file.
typedef d_Long kind;
Included for ODMG compatibility.
typedef o_4b o_err;
A VERSANT error code number.
typedef struct o_error {
o_err e_errno;
o_u4b e_oserr;
} o_error;
An error.
Elements:
e_errno
e_oserr
PObject
header file.
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()
.
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()
.
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
.
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()
.
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
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( o_err err_num );
PError
and specify an error handle as err_num
.
PError( o_err n, char* file, o_u4b line );
PError
(num, __HERE__
) usage.
~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.
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()
.
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.
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()
.
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()
.
o_err get_error_number();
Return the error number in this instance of PError
.
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
.
kind get_kind();
Included for ODMG compatibility.
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
.
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()
.
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.
static void pusherrorstack(
o_error errStack,
o_err err,
char* file,
o_u4b line
);
err
that has been retrieved by getcurrenterror()
or created by createerror()
.
See also: createerror()
, deleteerror()
, deleteerrortext()
, formaterrortext()
, getcurrenterror()
, seterrorparam()
.
static void seterrorparam(
o_error errStack,
const char* param,
const char* value);
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().
void set_kind(kind error_code);
Included for ODMG compatibility.
PResult
class is available if you include the PObject
header file.
PResult();
The constructor takes no arguments and initializes the internal state to O_OK
.
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.
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.
o_bool is_bad() const;
Return TRUE
if the internal state of this
instance of PResult
is not O_OK
and otherwise return FALSE
.
o_bool is_ok() const;
Return TRUE
if the internal state of this
instance of PResult
is O_OK
and otherwise return FALSE
.
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.
PVirtual
contains comparison, initialization, and activation methods.
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.
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.
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.
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.
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.
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.
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.
void mark_modified();
Mark this object as dirty.
The ODMG d_Object
class is aliased to PVirtual
.
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.
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.
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.
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.