This chapter describes the ObjectStore macros related to transactions and schema. See the ObjectStore Collections C++ API Reference for information on macros related to index maintenance.
Macros
OS_BEGIN_TXN_NAMED() is identical in behavior to OS_BEGIN_TXN() except that it allows you to specify a transaction name. The name must be unique among transactions in the same function. It is used in constructing statement labels.
OS_BEGIN_TXN ( txn-tag, expression, txn-type)or
...
OS_END_TXN ( txn-tag)
OS_BEGIN_TXN_NAMED ( txn-tag, expression, txn-type, txn-name)txn-tag is an identifier, a tag for the transaction that is not used for any other transaction in the same function. (The tags are used to construct statement labels, and so have the same scope as labels in C++.) The tag specified in a transaction's BEGIN and END must be the same.
...
OS_END_TXN ( txn-tag)
expression is of type tix_exception**, and specifies a location in which ObjectStore stores the transaction's completion status. If the tix_exception** points to 0 when the transaction completes, the transaction committed (that is, its changes were made permanent and visible). If the tix_exception** points to a tix_exception*, the transaction was aborted (that is, its changes to persistent state were undone), and the identity of the exception indicates the nature of the abort.
txn-type is one of
os_transaction::abort_only os_transaction::read_only os_transaction::updateos_transaction::abort_only indicates a transaction that can write to persistent data, but cannot be committed. See os_transaction::abort_only in ObjectStore C++ API Reference for further information.
os_transaction::read_only indicates that the transaction performs no updates to persistent storage. If write access to persistent data is attempted, a run-time error is signaled.
Caution: The macro arguments are used (among other things) to concatenate unique names. The details of macro preprocessing differ from compiler to compiler, and in some cases it is necessary to enter these macro arguments without white space to ensure that the argument concatenation will work correctly.
Locking
Locking in ObjectStore works as follows. When a persistent data item is read, the page on which it resides is read-locked by ObjectStore. When a data item is written, the page on which it resides is write-locked by the system. When another process attempts write access to an item on a read-locked page, the access is delayed until the outermost transaction (within which the access occurs) completes and the page is unlocked. Read access to a read-locked page is not delayed. When another process attempts read or write access to an item on a write-locked page, the access is delayed until the outermost transaction (in which the access occurs) completes and the page is unlocked. Transaction Aborts
When a transaction aborts, its changes to the database are undone, and the database is effectively restored to its state as of the moment the transaction began. In addition, if it is not nested, the transaction releases all its locks. User aborts
The user can specify that an abort occur at a certain point in the flow of control by invoking the member function os_transaction::abort() or os_transaction::abort_top_level(). System aborts
On rare occasions, the system aborts a transaction either because of a network failure or because it has determined that the transaction is involved in a deadlock. A simple deadlock occurs when one transaction holds a lock on a page that another transaction is waiting to access, while at the same time this other transaction holds a lock on a page that the first transaction is waiting to access. Each process cannot proceed until the other does, with the result that neither process can proceed. Other forms of deadlock are analogous. Two-Phase Commit
Two-phase commit is the process by which transactions that use multiple Servers commit in a consistent manner. The majority of transactions, which do not use multiple Servers, are unaffected by two-phase commit.
recovaux.C:1123(-2): This server is a participant in a multi server transaction recovaux.C:1127(-2): (id: 8 global id: 67372226,649525822,20971521) recovaux.C:1138(-2): The coordinator of the transaction is: recovaux.C:1143(-2): peachbottom recovaux.C:1147(-2): There are 2 blocks involved in the transaction on this server. Server startedThis indicates that during the restart process, the Server noticed that a multi-Server transaction was in the process of committing when the host system crashed. The information about transaction IDs can be used to match up outstanding transactions with other Servers that might also be recovering. The message about the coordinator indicates that it will receive the decision from that host (in this case, peachbottom) when that Server recovers.
During peachbottom's restart process, it too notices that a multi-Server transaction was in the commit process when the host crashed, and prints a similar message:
recovaux.C:1120(-2): This server is coordinator for a multi server transaction recovaux.C:1127(-2): (id: 6 global id: 67372226,649525822,20971521) recovaux.C:1130(-2): The transaction committed. recovaux.C:1135(-2): The 2 participant servers in the transaction are: recovaux.C:1143(-2): peachbottom recovaux.C:1143(-2): seabrook recovaux.C:1147(-2): There are 0 blocks involved in the transaction on this server. Server started(Note that it identifies the participant Servers, including itself.)
peachbottom then proceeds to notify seabrook of the decision for the transaction (committed), at which time seabrook prints the message
recovaux.C:1234(-2): Transaction committed recovaux.C:1252(-2): (id=8 global id: 67372226,649525822,20971521)The recovery is now complete for this transaction.
The pages that are involved in this transaction are in limbo during the commit phases as well as during the restart processing. However, during two-phase commit restart processing, it is possible for other requests to the Servers to be processed once they are started up. If one of those requests is for one of the pages that is being recovered as part of a multi-Server transaction that was committing, the client program receives an error indicating that the block is not recovered. This error is defined as
DEFINE_EXCEPTION(err_svr_blknotrecovered, "The block is blocked by an incomplete two phase commit", &err_svr);Once the recovery processing is done for the corresponding two-phase commit, the block becomes free to use again.
int main (int argc, char** argv) {Braces and semicolons are not necessary, as they are part of the macros.
OS_ESTABLISH_FAULT_HANDLER
... your code...
OS_END_FAULT_HANDLER
return value;
}
Note that these macros are only required for threads that use ObjectStore.
OS_MARK_QUERY_FUNCTION()
Applications that use a member function in a query or path string must call this macro. Form of the call
OS_MARK_QUERY_FUNCTION( class, func)class is the name of the class that defines the member function.
func is the name of the member function itself.
The OS_MARK_QUERY_FUNCTION() macro should be invoked along with the OS_MARK_SCHEMA_TYPE() macros for an application's schema, that is, in the schema source file, inside the dummy function containing the calls to OS_MARK_SCHEMA_TYPE(). No white space should appear in the argument list of OS_MARK_QUERY_FUNCTION().
OS_MARK_SCHEMA_TYPE( class)class is the class to be included in the application's schema. Typedef names are not allowed.
OS_MARK_SCHEMA_TYPESPEC(( type-name< x,y>))You can use this macro to parameterize types with multiple arguments. Note that you must place the type name and its arguments within a set of parentheses.
Calls to the macro should appear outside any function at global or file scope level.
You must mark every class on which the application might perform persistent new, as well as every class whose instances can be used by the application as database entry points. You must also mark every class that appears in a library interface query string or index path in the application.
If you supply the -make_reachable_source_classes_persistent flag to the schema generator (see ObjectStore Management), you do not actually need to mark every class that might be read from a database. This flag causes every class that is both defined in the schema source file and reachable from a persistently marked class to be persistently allocatable and accessible. It is useful in ensuring that items that could be overlooked, such as subtypes, are marked; however, it can also make classes persistent that do not need to be in order for compilation to succeed.
OS_REPORT_DLL_LOAD_AND_UNLOAD( os_boolean)Reports that a DLL has been loaded or unloaded.
If os_boolean is false, automatic reporting is not enabled and you must write your own code to call os_DLL_schema_info::DLL_loaded() and os_DLL_schema_info::DLL_unloaded() from the DLL's initialization and termination functions. The default is true.
OS_SCHEMA_DLL_ID( string)
You must call OS_SCHEMA_DLL_ID at least once in a DLL schema source file to distinguish it from an application schema.
OS_SCHEMA_INFO_NAME( name)
Updated: 03/31/98 17:30:18