Free Essay

Database Administration

In:

Submitted By ajith
Words 44539
Pages 179
VERSANT Dattabase Fundamenttalls Manuall VERSANT Da abase Fundamen a s Manua

June 2003

VERSANT Dattabase Fundamenttalls Manuall VERSANT Da abase Fundamen a s Manua

June 2003

VERSANT Database Fundamentals Manual

This page is intentionally blank.

2

VERSANT Database Fundamentals Manual

Table of Contents
Chapter 1: System Description ..............................................................................................................8 Versant Developer Suite 6.0: An Overview..........................................................................................9 VERSANT Features ........................................................................................................................12 Storage Architecture ......................................................................................................................22 Software Structure .........................................................................................................................24 Language Interfaces .......................................................................................................................25 System Usage Notes.......................................................................................................................28 Chapter 2: Objects.............................................................................................................................34 Object Types.................................................................................................................................35 Object Elements ............................................................................................................................37 Object Characteristics.....................................................................................................................38 Object Status.................................................................................................................................42 Object Relationships.......................................................................................................................44 Chapter 3: Sessions ...........................................................................................................................46 Session Boundaries ........................................................................................................................47 Session Memory Areas ...................................................................................................................48 Session Elements ...........................................................................................................................49 Session Types................................................................................................................................51 Units of Work ................................................................................................................................53 Session Operations ........................................................................................................................54 Chapter 4: Transactions......................................................................................................................55 Short Transactions .........................................................................................................................56 Long Transactions ..........................................................................................................................62 Chapter 5: Locks ...............................................................................................................................66 Short Locks ...................................................................................................................................67
3

VERSANT Database Fundamentals Manual

Persistent Locks .............................................................................................................................85 Chapter 6: General Programming Notes ...............................................................................................95 Name Rules...................................................................................................................................96 Session Firewall .............................................................................................................................99 Database Connection Rule ............................................................................................................ 100 Schema Evolution ........................................................................................................................ 101 Mixing Releases........................................................................................................................... 106 Application Failure ....................................................................................................................... 107 Error Messages that are Incomplete................................................................................................ 108 Chapter 7: Object Movement............................................................................................................ 109 Object Movement Overview ......................................................................................................... 110 Object Migration.......................................................................................................................... 111 Object Checkout.......................................................................................................................... 113 Object Checkin............................................................................................................................ 118 Chapter 8: Object Versioning and Configuration Management .............................................................. 121 Object Versioning ........................................................................................................................ 122 Configuration Management........................................................................................................... 132 Chapter 9: Object Sharing ................................................................................................................ 158 Mixing C and C++ Code and Objects.............................................................................................. 159 Chapter 10: Optimistic Locking ......................................................................................................... 168 Optimistic Locking Overview ......................................................................................................... 169 Optimistic Locking Actions ............................................................................................................ 171 Multiple read inconsistencies......................................................................................................... 178 Optimistic Locking Prototocol ........................................................................................................ 179 Optimistic Locking General Notes .................................................................................................. 184 Examples .................................................................................................................................... 186 Chapter 11: Memory Management .................................................................................................... 195 Overview .................................................................................................................................... 196
4

VERSANT Database Fundamentals Manual

Object Cache .............................................................................................................................. 197 Server Page Cache ....................................................................................................................... 203 Software Modules........................................................................................................................ 204 Multi-Threaded Database Server ................................................................................................... 207 Process Usage Notes .................................................................................................................... 211 Chapter 12: Multiple Processes in a Single Session .............................................................................. 215 Multiple Process Session Concepts ................................................................................................ 216 Multiple Process Session Operations .............................................................................................. 217 Multiple Process Session Usage Notes ............................................................................................ 220 Chapter 13: Multiple Threads............................................................................................................ 227 Thread and Session Alternatives .................................................................................................... 228 Thread and Session Concepts and Terms ........................................................................................ 229 Session Management ................................................................................................................... 232 Thread Management .................................................................................................................... 238 Multiple Threads in the Same Session............................................................................................. 241 Thread Example Programs in C++ .................................................................................................. 245 Chapter 14: Performance Tuning....................................................................................................... 262 Performance Statistics .................................................................................................................. 263 Data Modeling ............................................................................................................................ 266 Memory Management .................................................................................................................. 269 Disk Management........................................................................................................................ 276 Message Management ................................................................................................................. 283 Multiple Applications.................................................................................................................... 285 Application Programming.............................................................................................................. 287 Chapter 15: Statistics Collection ........................................................................................................ 290 Statistics Collection Overview........................................................................................................ 291 Statistics Quick Start..................................................................................................................... 293 Collect Statistics and Store Them in a File ........................................................................................ 299
5

VERSANT Database Fundamentals Manual

Collect Statistics in Memory and View in Real Time .......................................................................... 301 Get Statistics Parameters............................................................................................................... 302 Collect Derived Statistics .............................................................................................................. 303 Statistics Suggestions ................................................................................................................... 304 Statistics Collection Usage Notes ................................................................................................... 307 Statistics Names........................................................................................................................... 309 Chapter 16: Garbage Collection ........................................................................................................ 327 Concepts .................................................................................................................................... 328 Garbage Collection Policy Suggestions ........................................................................................... 329 Garbage Collection Safety............................................................................................................. 330 Chapter 17: Event Notification........................................................................................................... 331 Overview .................................................................................................................................... 332 Event Notification for C and C++ .................................................................................................... 335 Event Notification Performance Statistics......................................................................................... 360 Asynchronous Database Replication............................................................................................... 361 Chapter 18: Roll Forward Archiving ................................................................................................... 365 Roll Forward Concepts ................................................................................................................. 366 Roll Forward Management ............................................................................................................ 367 Roll Forward Usage Rules.............................................................................................................. 369 Roll Forward Procedures ............................................................................................................... 370 Chapter 19: Fault Tolerant Server ...................................................................................................... 372 Concepts .................................................................................................................................... 373 Procedures ................................................................................................................................. 374 Usage......................................................................................................................................... 378 Chapter 20: Controlling Access to Database........................................................................................ 384 Database Users............................................................................................................................ 385 User Authentication ..................................................................................................................... 388 User Privileges............................................................................................................................. 408
6

VERSANT Database Fundamentals Manual

Chapter 21: Internationalization......................................................................................................... 410 Overview .................................................................................................................................... 412 Developing applications using Versant Internationalization ................................................................ 414 Versant Localization ..................................................................................................................... 420 Localizing VERSANT View............................................................................................................. 428 Chapter 22 : Embedding Versant Utilities in Applications ...................................................................... 435 APIs ........................................................................................................................................... 436 SS daemon enhancements ............................................................................................................ 440 Chapter 23: Query Processing........................................................................................................... 441 Search Queries ............................................................................................................................ 444 Search Query Indexes .................................................................................................................. 464 Cursor Queries ............................................................................................................................ 481 VQL Queries ............................................................................................................................... 498 Advanced Queries ....................................................................................................................... 518 Index ............................................................................................................................................. 525

7

VERSANT Database Fundamentals Manual

Chapter 1: System Description
Versant Developer Suite 6.0: An Overview..........................................................................................9 Salient Features of Versant Developer Suite 6.0:...............................................................................9 Scalability & 64-bit support.........................................................................................................9 Query......................................................................................................................................9 Security .................................................................................................................................10 Internationalization (i18N) Support............................................................................................10 Embeddability Enhancements...................................................................................................11 VXML Toolkit .........................................................................................................................11 Integrated Installation ..............................................................................................................11 VERSANT Features ........................................................................................................................12 List of Features...........................................................................................................................12 Scalable Operation .....................................................................................................................15 Distributed Databases.................................................................................................................16 Workgroup Support ...................................................................................................................18 Performance ..............................................................................................................................20 Storage Architecture ......................................................................................................................22 Software Structure .........................................................................................................................24 Language Interfaces .......................................................................................................................25 C/VERSANT Interface.................................................................................................................25 C++/VERSANT Interface.............................................................................................................25 Sharing C++ Objects...................................................................................................................26 J/VERSANT Interface..................................................................................................................26 Standards..................................................................................................................................27 System Usage Notes.......................................................................................................................28

8

VERSANT Database Fundamentals Manual

Versant Developer Suite 6.0: An Overview
A key part of Versant's application framework is Versant Developer Suite 6.0, a complete, e-infrastructure software that simplifies the process of building and deploying transactional, distributed applications. As a standalone database, the Versant ODBMS is designed to meet customers' requirements for high performance, scalability, reliability and compatibility with disparate computing platforms and corporate information systems. Versant ODBMS has established a reputation for exceeding the demands of mission critical enterprise business applications, providing reliability, integrity, and performance. The efficient multi-threaded architecture, internal parallelism, balanced client-server architect and efficient query optimization of 6.0.5 ODBMS delivers unsurpassed levels of performance and scalability. This release focuses on three key areas, designed to meet the expanding requirements for today's traditional and Internet-based database solutions: internationalization, scalability, and productivity. The Versant Developer Suite includes the Versant ODBMS, the C++ and Java language interfaces, the XML toolkit and Asynchronous Replication framework. The main advantage is that all Versant products included in the Versant Developer Suite, work cohesively together, conform to the same compiler (C++, JDK) versions and adopt the same release schedule. From an ease-of-use perspective, this is a significant step in the right direction.

Salient Features of Versant Developer Suite 6.0:
Scalability & 64-bit support
Significant enhancements have been made to enable the Versant ODBMS to continue to scale with the demands of our customers. Particular focus has been placed on supporting today's generation of 64 bit operating systems. To this end Versant Developer Suite 6.0 will natively support both the 64 and 32-bit models. The 32-bit model is specifically for customers with dependencies on other 32-bit products, whilst the 64-bit release allows massive scaling. This release of Versant ODBMS will support system, backup and archive files larger than 2GB.

Query
Extensions to the query capabilities, which with specified criteria will return result(s) in near constant time, irrespective of number of objects. In 6.0.5 release, Versant introduced the concept of Virtual Attributes that allows you to define derived attributes that are dynamically computed from real class attributes. These derived attributes or “virtual attributes” can have indices defined on them to improve query performance.
9

VERSANT Database Fundamentals Manual

The supported "Virtual Attributes" for the 6.0.5 release include: 1. Multi- attribute The ability to define a virtual attribute composed from a number of actual attributes. This will help improve query performance for multi- attribute predicates. 2. Case Insensitive The ability to perform case insensitive string queries. 3. Internationalized Strings The ability to perform queries based on international character sets (see later).

Security
Enable user authorization independent of operating system while maintaining backward compatibility with existing applications. The following functionality has been added: • • • Removed OS user dependency during user authentication (excludes DBA's and DBSA) Password based authentication for users (exclude DBA's and DBSA) Provided an option to run SS daemon to run as a user (typically DBA)

Internationalization (i18N) Support
The Versant ODBMS has been enhanced to support the storage and retrieval of strings that use international character sets and, in conjunction with the query enhancements, query them. Versant has certified that 8-bit dean (UTF-8) character encodings, are stored and manipulated correctly internally, it is possible to use such encodings for: • • • Database names User names & passwords String attribute values

The query enhancements make it possible to build and use indexes and query based on the character encoding and language (locale). For example it would be possible to encode strings as UTF -8 and query these based on the German locale (U and Ü are treated the same). Likewise it would be possible to build an index based on this specific locale to improve performance.

10

VERSANT Database Fundamentals Manual

Embeddability Enhancements
By introducing a number of new APIs it is now possible to manage a Versant environment completely via API from C, C++ or Java. This functionality is significant for those wishing to embed Versant in their own applications.

VXML Toolkit
The Versant XML Toolkit (VXML) adds XML/object mapping support to the Versant Developer Suite product. Via command line tools or Java APIs users can generate XML from defined object graphs and likewise generate objects from XML.

Integrated Installation
A common, integrated installation offers a single GUI interface to install data-management and connectivity components. This integrated installation eliminates version conflicts when installing and deploying components of the Developer Suite.

11

VERSANT Database Fundamentals Manual

VERSANT Features
List of Features
Following is a raw list of VERSANT features.

General Description — VERSANT is an object database management system that includes all features needed for scalable, production databases in a distributed, heterogeneous workgroup environment. Data as Objects — VERSANT models data as objects. The VERSANT implementation of objects allows:
• • • • • • Custom definition of complex data types. Encapsulation of data and code. Inheritance of data and code. Code reuse. Polymorphism. Unique identification of objects.

Database Features — VERSANT database features include:
• • • • • • • • • • • Persistent storage of data. Concurrent access by multiple users. Concurrent access to a session by multiple processes or threads. Multiple sessions, including sessions containing no processes. Transaction management. Recovery from system failures. Navigational and search condition queries. Remote database connections. Data versions.

User defined security. • Two-phase commits. You can create a distributed database system containing a combined total of 2^16 databases. • Multiple standard language interfaces. • Heterogeneous platforms. Use of multiple threads by the database server. Use of multiple latches by the database server. Unique indexes.

• • •

12

VERSANT Database Fundamentals Manual

The C++/VERSANT interface allows: • • • • • • • • • Association of data with links and arrays of links. Extensible data types. Parameterized types. Embedding of objects. Containers and collections of objects.

Support for the Standard Template Library Support for Rogue Wave Tools.h++ Support for ODMG-93. Support for multiple compilers.

The J/VERSANT interface allows: • • • • • • • • • • Support for elemental data types as well as references. Extensible data types. Seamless support for garbage collection. User to specify class of persistence. Persistence by reachability. Support for JDK 1.2 Collections.

Support for multi-threaded applications. Transparent event notification. Support for ODMG. Layered database APIs providing transparent and fundamental access to objects.

Database System — VERSANT database system features support:
• • • • • • • • • • • • • • Distribution of data, including the ability to migrate objects. A client/server model of hardware utilization. Query processing on servers. Dynamic management of database schema. Tuning options for applications and databases. Object level locking. Object caching on the client and page caching on the server. Clustering of instances of a class. Either raw devices or files for data storage. Indexing for query optimization. Ability to turn locking and logging on and off. Checking out of objects to provide local access. On supported platforms and interfaces, multiple process or multiple thread applications. Data replication on numerous databases.

13

VERSANT Database Fundamentals Manual

Database Administration — VERSANT database administration utilities support:
• • • • • • Creating, expanding, and deleting databases. Backing up data. User authorization. Custom system configurations. Modification of data definitions. Creation of classes at run time.

Application Programming — Application programming features include support of:
• • All features of access languages, including flow of control. VERSANT provides application programming interfaces for C, C++, and Java. You can also access databases with SQL statements and parse the results with C or C++ routines using the VERSANT Query Language. • Custom and third party libraries of code and data types. • Multiple kinds of atomic work units, including short transactions, checkpoints, savepoints, nestable transactions, and long transactions. • Predefined data types and management routines. • Proprietary and third party programming tools. • Control of process and shared memory, including explicit pinning of data. • Error handling mechanisms. • Application debugging facilities.

Physical Database — A VERSANT database system physically consists of:
• • • • • • • System files. Executable utilities. Header files. Link libraries. Class libraries for each language interface. Application development tools. At least one database consisting of storage and log volumes, which are files or raw devices.

How to Use VERSANT — To use VERSANT:
• • Create data definitions and applications using VERSANT routines along with normal interface commands and methods. In your application, before saving or retrieving persistent objects, start a database "session." A session is a period of time in an application during which a VERSANT memory workspace exists in process memory or shared memory and during which you have access to at least one VERSANT database.

For the C and C++ interfaces: • Include relevant VERSANT header files and then compile and link with a VERSANT compiled code library to create an executable program.

14

VERSANT Database Fundamentals Manual

For the Java interfaces: • Use the JVI Enhancer that post-processes the compiled class byte-code to provide transparent persistence.

Scalable Operation
VERSANT is scalable, which means that it uses distributed resources in such a way that performance does not decrease as the system grows. VERSANT is scalable because of the following features. Client/server model VERSANT uses a client/server model of computing. Your application is the database client and runs on a client machine. A client application can access multiple databases concurrently with other client applications. The database that provides objects to an application is called the "server." One of the roles of the server is to process queries. A server can support concurrent access by numerous users. To VERSANT, the terms "client" and "server" refer to roles and not machines or processes. The client and server can be on the same machine or on different machines. Because queries are executed on the platform containing the data and because locks are set at the object level, network traffic is reduced to a short query message from the client to the server and the return of only desired objects from the server to the client. Processing queries on servers balances database processing responsibilities between the client and the server. It can result in major performance gains in a large, distributed database environment by taking full advantage of available platform and network resources including parallel and scalable processors. By contrast, a file/server query causes all objects of a class to be locked and passed over a network even if only one object is desired.

15

VERSANT Database Fundamentals Manual

Communication between client and server is via TCP/IP.

Locks The VERSANT locking model provides for high concurrency of multiple users. Volumes can be anywhere Objects are kept in one or more database volumes, which are storage places on disk. Database volumes can be files or raw devices and can be added incrementally either locally or at distributed locations. Two-phase Two-phase commits To ensure data integrity when multiple, distributed databases are used, VERSANT performs updates with two-phase commits. Two-phase commits involve a procedure in which multiple databases communicate with each other to confirm that all changes in a unit of work are saved or rolled back together. Lazy updates Changes to class definitions do not paralyze operations. Instead, instances are updated the next time they are accessed, which is called a "lazy update." You can create or drop leaf classes, rename leaf or non-leaf classes, and create or drop attributes and methods in leaf or non-leaf classes. Schema management To facilitate the use of distributed databases, you can ask an object the name of its class and then inspect its class definition. Routines are also provided for creating and modifying classes at runtime and for synchronizing class definitions among multiple databases.

Distributed Databases
VERSANT supports distributed databases with the following features.

16

VERSANT Database Fundamentals Manual

Object migration Objects can be migrated while applications still have transparent access to them. Object migration is possible, because objects have identifiers that stay with the object for its lifetime which means that the physical locations of objects are hidden from the application. Recovery To ensure data integrity when multiple, distributed databases are used, VERSANT performs updates with two-phase commits. Two-phase commits involve a procedure in which multiple databases communicate with each other to confirm that all changes in a unit of work are saved or rolled back together. Heterogeneity Objects can be moved among heterogeneous platforms and managed in databases on numerous hardware platforms to take advantage of available resources in a network. Schema management Class definitions can be managed at run time on both local and remote databases. Class definitions are stored with objects, which allow access to objects with applications that are running on different platforms and are using multiple interface languages. Replication Advanced functionality includes group checkouts, which can replicate data on numerous databases. Expansion Databases can be created, deleted, and expanded on local and remote platforms. Database volumes can span devices and platforms. Backup Data on one machine can be backed up to remote sites, tapes, or files. Multiple distributed databases can be backed up to save their state at a given point in time. This gives transactional consistency across multiple databases. Security Access to databases and system utilities is controlled through user authorization, which may be customized.

17

VERSANT Database Fundamentals Manual

Session database VERSANT implements the concept of a session database, which can be local or remote, which handles basic record keeping and logging for a session. Connection database Applications can connect to any number of local or remote databases and then manage objects in them as if they were local. You can work on objects in any number of databases at the same time in a distributed transaction.

Workgroup Support
VERSANT supports workgroups with the following features. Locking Locks allow multiple applications to access the same objects simultaneously in a cooperative, controlled, and predictable manner. To maximize concurrency, locks are applied at the object level. There are two basic kinds of VERSANT locks. Short locks reserve objects during a short transaction typically lasting only seconds or minutes. Persistent locks have the same features as a short lock, plus persistence from session to session and the ability to set multiple levels of locking priorities. They also specify queuing options when the object you want is not available, and notification of lock related actions performed by other applications. Object level locking Object level locking provides for maximum access to data while providing read and modification guarantees. Two types of databases VERSANT allows you to create two kinds of databases: group databases, which are accessible to many users, and personal databases, which are only accessible to one user at a time. Checkouts Checking out of objects provide local access to objects over long periods of time. Personal checkouts copy objects from a group to a personal database, which is useful when you want to update a set of objects over a long period of time without network traffic or local logging or locking. During the checkout period, VERSANT places persistent locks which hold even if you disconnect from the source database. Checked out objects are tracked in long transactions.
18

VERSANT Database Fundamentals Manual

Group checkouts copy objects from one group database to another group database and are useful when you want to replicate a set of objects in many locations that may be physically far apart. Versions Versioning allows you to trace the evolution of an object over time and is also a way of allowing multiple users to work on the same data. Configuration Management Configuration management allows customized sets of object versions. Variety of transactions VERSANT supports multiple kinds of atomic work units, including short transactions, checkpoints, savepoints, and long transactions. Short transactions are for use when objects are needed for short periods of time, and long transactions are for use when objects are needed for hours or days. Standard interfaces Multiple standard language interfaces allow workgroup members to access data from applications written in multiple languages. The language specific interfaces map all capabilities and programming styles of a particular language to the object database model. Any action or data type that can be expressed in the interface language may become a part of a VERSANT database schema. Thus, programming languages are tightly bound to the database, but the database is not tightly bound to a particular language. There is no special VERSANT database language. VERSANT object databases are most commonly used with languages that implement the concept of either class or template and either delegation or inheritance. VERSANT can also be used with languages, such as C, which are not object oriented. In its present release, VERSANT provides language specific interfaces for C++ and C. Each language-specific interface consists of several libraries of precompiled routines and, for typed languages, predefined data types. An interface can include its own development tools, and can be used with other vendors' software development products. Compilers and debugging facilities VERSANT supports multiple compilers and debugging facilities.

19

VERSANT Database Fundamentals Manual

Libraries You can use VERSANT with custom and third party libraries of code and data types. Tools VERSANT supports a variety of proprietary and third party programming tools. Shared memory cache Database servers maintain a page cache in shared memory. Custom lock models For situations requiring unusual types of access, you can define your own locks. Object migration Because object are persistently and uniquely identified, objects can be redistributed in a system of databases for performance improvements without affecting application code making object references.

Performance
VERSANT performance features include the following. Object and page caches During a database session, VERSANT maintains an object cache in virtual memory on the client machine and a page cache in shared memory on server machines with a database in use. There is one object cache per application, and one page cache per operating database. This approach combines the best of a page management scheme and an object management scheme, because the object cache provides for fast access to objects needed in the current transaction while the page cache provides fast access to objects used in preceding transactions and to objects stored on the same page as a recently accessed object. Memory management VERSANT provides numerous mechanisms for managing application memory, including explicit pinning and releasing of data. Process tuning VERSANT allows you to set operating parameters for application and server processes.
20

VERSANT Database Fundamentals Manual

Clustering You can cluster instances of a class on disk storage, which will improve query performance. Raw devices You can use either raw devices or files for data storage. Indexing You can create indexes on attributes, which will improve query performance. Locking and logging on or off You can turn locking and logging off to improve performance. Turning locking off is safe in a personal database, because there can be only one user of a personal database at a time. Turning logging off is safe if used in conjunction with checkouts, because original copies of objects remain in their source databases. Multiple processes and threads You can use multiple processes or threads in a session. You can also establish multiple sessions. Navigational queries You can use object references to navigate to related objects. Local access You can checkout objects to provide local access, which reduces network traffic.

21

VERSANT Database Fundamentals Manual

Storage Architecture
Each database consists of a number of volumes, which are storage places on disk. A volume can be either a file or a raw device. Database volumes are: System Volume The System Volume for each database is automatically created as a part of the initial process of creating a database. It is used for storing class descriptions and for storing object instances. Data volumes Additional data volumes can be added to a database to increase capacity. Logical Log Volume Physical Log Volume The Logical Log Volume and Physical Log Volume are used to record transaction activities and provide information for roll back and recovery. Logical log and physical log volumes are created when a database is created. The basic storage architecture is:

There is no structural difference between personal and group databases. The maximum number of databases that can be combined to form a distributed database system is 216.

22

VERSANT Database Fundamentals Manual

For the C and C++ interfaces, applications and VERSANT libraries are stored as files. When you create classes or an application, you write a program that includes appropriate VERSANT .h specification files. You then compile your program and then link it with appropriate VERSANT .a library files. With the C++ Interface, you must also insert your classes into a database with the Schema Change Utility sch2db.

23

VERSANT Database Fundamentals Manual

Software Structure
Internally, VERSANT is composed of several software modules. You do not need to know about these software modules, for they operate invisibly. Thus, this section is provided for your interest only. VERSANT Manager From a developer's viewpoint, programs using language interfaces drive all database and object management actions by communicating with a module called "VERSANT Manager." VERSANT Manager then communicates with a module called "VERSANT Server." VERSANT Manager performs object caching, object validation, and management of queries, long transactions, schema, links, versions, checkouts, and checkins. VERSANT Server VERSANT Server performs object retrieval, object update, page caching, query support, and management of storage classes, indexes, short transactions, logging, and locking. Virtual System Layer Between a VERSANT Server and an operating system is a Virtual System Layer specific to the hardware platform. The Virtual System Layer provides portability across hardware boundaries. Internal communications occur through network layers. The network layers translate messages as appropriate to the network protocol. Because of this form of internal communication, a VERSANT Manager may communicate transparently with all parts of a distributed database network.

24

VERSANT Database Fundamentals Manual

Language Interfaces
Language-specific interfaces map the capabilities and styles of a programming language to the object database model. Any action or data type that can be expressed in the interface language can become part of a VERSANT database schema. This means that you use standard language statements to manipulate VERSANT. There is no special VERSANT database language. VERSANT object databases are most commonly used with languages that implement the concept of either class or template and either delegation or inheritance. VERSANT can also be used with languages, such as C, which are not object oriented. In its present release, VERSANT provides language specific interfaces for C++ and C. Each language-specific interface consists of several libraries of precompiled routines and, for typed languages, predefined data types. An interface can include its own development tools, and can be used with other vendors' software development products.

C/VERSANT Interface
The C/VERSANT interface can take advantage of most object model capabilities, including the ability to define embedded, association, inheritance, and version relationships. C/VERSANT also implements all VERSANT database functionality as both functions and utilities. There is, however, no messaging concept in the pure C environment: when you define methods they are executed as functions. Also, there is no runtime binding to functions, inheritance is limited to virtual inheritance, and there is no concept of private versus public functions.

C++/VERSANT Interface
The C++/VERSANT interface implements the full object model. Methods are provided to define embedded, association, inheritance, and version relationships, either at compile time or at runtime. C++/VERSANT also implements complete VERSANT database functionality as both functions and utilities. C++/VERSANT functionality is available through standard C++. This includes dynamic access to the database schema for runtime type checking, locating subclass and superclass information, and identifying class attributes. Any persistent class can have transient and persistent instances simultaneously.

25

VERSANT Database Fundamentals Manual

Sharing C++ Objects
Although VERSANT stores objects in such a way that they can be accessed by C++ applications, there are differences in the C++ languages that limit object sharing. Following is an explanation of the VERSANT and C++ data models. Database object model A VERSANT database stores schema information in class objects and data in instance objects. The information in the class objects is slightly different depending on what language defined the class, but the objects are accessible to all supported language interfaces. C++ data model Classes defined by C++ may have multiple inheritance, the attribute names of superclasses may be the same as attribute names in derived classes, and classes may be embedded as attributes. Associations among objects may be defined with links. In order to allow multiple inheritance and class embedding, VERSANT assigns a unique database name to each attribute. This name normally consists of the class name concatenated with the attribute name. If the attribute type is another class, the database attribute name is a concatenation of the class name, the embedded class name, and the attribute name. For C++/VERSANT applications, the storage layout of an object is defined at compile time. Even though the storage layout may be different among different C++ compilers, at run time the compiler assumes that the object has a fixed size and layout, and that each attribute is of a particular domain.

J/VERSANT Interface
JVI (Java Versant Interface) implements the full object model. Methods are provided to define embedded, association and inheritance relationships, either at compile time or at runtime. JVI also implements complete VERSANT database functionality as both functions and utilities. JVI functionality is available through standard Java. This includes dynamic access to the database schema for runtime type checking, locating subclass and superclass information, and identifying class attributes. Any persistent class can have transient and persistent instances simultaneously. For more information about the JVI language binding, refer to the JVI documentation.

26

VERSANT Database Fundamentals Manual

Standards
Versant Object Technology Corporation is involved in efforts to define industry standards. Versant is committed to and/or working on the following: • ISO 9001 Registration for Company-wide Quality Management Systems. • • • • • Object Management Group (OMG). Object Database Management Group (ODMG). ANSI (American National Standards Institute) X3H2 Structured Query Language, X3H7 Object-Oriented Information Systems, X3J4 Object-Oriented COBOL Task Group, X3J16 C++. ECMA (European Computer Manufacturers Assoc.) PCTE (Portable Common Tools Environment). PDES/STEP.

27

VERSANT Database Fundamentals Manual

System Usage Notes
VERSANT provides a lot of features. It is up to you to decide how best to use them for your needs. VERSANT is designed for use as a high-speed, production database in a complex, scalable, heterogeneous, client/server, workgroup environment. Accordingly, it has numerous features that allow you to perform almost any database task. If you are an experienced database developer or object programmer, then you will immediately appreciate the power and flexibility that VERSANT offers. If you are new to databases and/or object programming, the number of VERSANT features is so large that VERSANT may be overwhelming at first. Accordingly, no matter what your background, we recommend training, either by VERSANT or by third party vendors. Although our customers and industry studies report order of magnitude gains in productivity with the use of object programming and object databases, most also report that an initial period of training in the concepts involved has a high payoff. Versant also offers on-site consulting, which can help during the start of the programming phase of a project. For information about VERSANT training classes or on-site consultation, please call the Versant Training and Consulting Group. Once you understand the underlying concepts, you will find VERSANT to be logical and predictable. VERSANT is an expression of the object model of data with familiar and natural models for database management and interface usage. However, the object model, normal database procedures and protocols, and VERSANT must all be understood in order to create efficient application programs. VERSANT is a powerful and flexible database system. VERSANT has most features and options found in modern database systems. For example, VERSANT has four different ways to retrieve objects, seven types of locks, and numerous transaction alternatives. Among other things, you can move objects among databases, change schemas, tune performance, create classes at run time, invoke database administration utilities at run time, and move databases after they have been created. If you do not have a database background, you must understand that VERSANT provides database features that go far beyond mere object storage. To benefit from these features, you must know how to use them. For example, you must know when to use update locks or else, in a workgroup environment, your program will tend to get deadlock errors. You must use group operations to retrieve and update large numbers of objects, to reduce network traffic. You must use cursor queries instead of simple
28

VERSANT Database Fundamentals Manual

queries to reduce the size of the result set. Also, you must remember to turn locking and logging on when using VERSANT in a production environment, and, as with any production system, you must remember to perform frequent database backups. VERSANT uses object languages. VERSANT supports all computational and control features found in its interface languages. It also extends these languages to provide database, memory management, and process control features. For example, VERSANT has numerous functions that control memory, five options for session memory workspaces, low-level and high-level variable-length storage types, provision for controlled use of shared memory by multiple processes, and multiple language, hardware, and compiler interfaces. If you have a database background, you must learn about the best way to implement various tasks. For example, you must know that although links are always safe, you must not use pointers to unpinned objects. VERSANT implements the object model of data. VERSANT implements the object model of data, which provides an extraordinary amount of power and flexibility. For example, VERSANT allows you to define your own data types and establish inheritance, embedded, and association relationships among objects. The advantages of using objects include dramatic gains in programming productivity and the ability to create applications that were not previously practical. However, these gains depend upon an understanding of the object model. If you have a relational database background, you must learn the differences between is-a (inheritance), has-a (association), and contains-a (embedded) relationships, and that most objects are found by following links rather than by performing queries. If you have a procedural programming background, you must learn about messages and classes and learn that switch statements are rarely needed. VERSANT extends operating system functionality. VERSANT extends operating system functionality, which provides important benefits in a heterogeneous, workgroup environment. For example, VERSANT provides heterogeneity among platforms, compilers, and languages and provides controlled use of shared memory. It uses a client/server model, which means that VERSANT is scalable and provides for the beneficial use of additional hardware resources. No matter what your background, the extensions that VERSANT provides must be understood to be
29

VERSANT Database Fundamentals Manual

used. There are new procedures and new usage conventions. VERSANT concepts are orthogonal but mutually supportive. VERSANT is a complete database system with orthogonal session, locking, interface, usage, versioning, and object management models. Because they are orthogonal, the usage, database, and interface models provide flexibility; however, they must be used together in a consistent manner in order to achieve results. For example, you must be in a session before you can interface with a database. Some elements of VERSANT, such as the data model and database administration, are language independent. Other elements, such as the interface model, rules, conventions, and usage are language specific. Also, VERSANT users have, inevitably, different backgrounds and skill levels. Because interface dependent and interface independent elements are orthogonal but interrelated, a systematic presentation of VERSANT is necessarily arbitrary. There is no sequential, lock-step way to explain VERSANT or, for that matter, any other database system. VERSANT should be used in the context of good software engineering practice. As with any programming project, the principal phases of a VERSANT application development effort are analysis/design, development/testing, and deployment/ maintenance. Following are brief comments related to each of these project phases. Analysis You must have a firm understanding of your situation and project goals before beginning development of your application. Design Experience suggests that the design phase of software development is even more critical to the success of object oriented projects than it is to procedural programming projects. The reason is that the object programming development lifecycle becomes shorter with a higher percentage of the time spent understanding the problem to be solved and designing the needed classes. If you have a good design for the classes in your application, implementation proceeds far more smoothly than with non-object oriented languages. We recommend using a design methodology such as Booch and Rumbaugh along with a CASE tool to record your design. Development/Testing During the Development phase of software development, it is critical to understand that database transactions and the support of multiple users are significant considerations. Experience suggests that you cannot "retrofit" transactions and concurrency into an application that assumes all of its data is in memory and, thus, ready to be modified at will. Also, you should carefully identify whether there are any bottleneck objects that must be write-locked by many transactions and will thus be a disproportionate
30

VERSANT Database Fundamentals Manual

source of lock contention. Important development issues are: 1. 2. 3. 4. 5. 6. Review of the object model (classes and associations) in the light of implementation issues. Navigation model (how do you move from object to object.) Transaction model (how do you maximize concurrency and define units of work.) Distribution model (how to maximize available resources.) Usage model (how users interact with the application and what tasks are most performed.) Performance tuning.

Testing is a key component of any development project. Test to be certain that each of your classes do what you expect. Test your database code not just with a single user, but also with the use load you expect in production. Often, multi-user testing uncovers subtle flaws in an application's locking and data-sharing strategy. Class-level unit testing is essential early in development to catch minor design problems before they turn into major rework headaches. Integration testing and multi-user testing is essential to ensure the system works as you intend. Acceptance testing is critical to ensure that the application meets the user's expectations. Because design and development work interact, you will probably want to iterate through the design and development stages numerous times. You will probably also want to iterate through development and deployment, where a "semi-final" deployed product results from each iteration. For example, performance tuning is an issue that is often considered during development/deployment iterations. Deployment/Maintenance You should design and implement your application with deployment and maintenance in mind. How will users build, maintain, backup and restore your database? Where will your software reside on the system? How will you reliably move your software from your development environment to your user's machine? How will you handle upgrades to your software and database schema? VERSANT provides tools and services to assist with all these tasks, and you can use third party tools with VERSANT, but the primary responsibility to ensure that each phase is successful rests with you, the software engineer and project manager. Ten Tips for Success Based upon our experience with customers, following are ten tips for success in using VERSANT. This is not
31

VERSANT Database Fundamentals Manual

meant as a definitive list of success tips, just a few suggestions based upon common problems. Spend time on design. Most projects do not spend enough time mapping logical designs to physical designs. The most important thing is to identify the various objects that will be used and the operations that will be performed on them. Prototype with a realistic amount of data. Everything runs fast with fifty objects. Many design issues, bugs, and performance problems tend to surface only when databases similar in size to the target production environment are used. Test with multiple users. When an application is deployed, concurrency issues are often the most important factor in performance. Use the same hardware as the user. Developers tend to have high performance machines. It is important to determine what running an application will be like for end users with more modest machines. For example, an application may run quickly on a machine with a large amount of physical memory but become sluggish on a smaller machine due to virtual memory paging. Gather and log performance data on an regular basis. We suggest that you write monitoring code that can be turned on and off and also write external scripts that log resource consumption in various sectors of your programs. Data of this kind is extremely useful both in debugging and in performance tuning. Use your computers around the clock. You can use scripts to perform database administration, run batch jobs, prepare reports, and run long test programs when you are not around. One of the most important factors in a successful deployment is rigorous testing under a wide variety of conditions. Sometimes, problems don't show up until a program has been running for days or weeks or tested with extremely large numbers of objects or users. If you run your machine constantly, every time you run into a problem, you can add a unit test to a growing suite of automated tests that can be re-run every time you make a change of any kind. Keep short transactions short and hold locks for a minimum amount of time. Open transactions hold locks, so avoid "think times" in which a short transaction is open while the application waits for user input. Holding key objects locked will block other users from doing work. Alternatives are to use timeouts during screen input/output or to gather all input from the user before
32

VERSANT Database Fundamentals Manual

updating objects. Use update locks when appropriate. In a multi-user environment, you cannot assume that you will always be the next person to convert a read lock to a write lock. For example, programming the following sequence of events is deadlock prone: begin transaction read objects write lock selected objects update selected objects end transaction

Update locks allow you to read objects without blocking other readers. They have the additional advantage of guaranteeing you the next write lock. Invest in training on a regular basis. Training in object languages and VERSANT typically pays for itself ten times over. There is so much power and flexibility in using objects that taking time to just learn what can be done is time well spent.

33

VERSANT Database Fundamentals Manual

Chapter 2: Objects
VERSANT databases model data as objects. This chapter provides an explanation of the VERSANT object data model. Object Types.................................................................................................................................35 Object Elements ............................................................................................................................37 Object Characteristics.....................................................................................................................38 Object Status.................................................................................................................................42 Object Relationships.......................................................................................................................44

34

VERSANT Database Fundamentals Manual

Object Types
Software objects are a response to programming issues inherent in large and complex software applications. Objects are useful if you want to organize large amounts of code, handle complex data types, model graph structured data, perform navigational queries, and/or make frequent modifications to applications. The term "object" has numerous meanings, which are clear in context. Following is listing of object types. Object A database "object" is a software construction that can encapsulate data and references to other objects. Usually, the generic term "object" refers to an object containing data, but it can also refer to other kinds of objects. Instance object A database object that holds data is called an "instance object". In a VERSANT database, an object has a class that defines what kinds of data are associated with the object. Elemental (immediate) values are stored as typed values. Class object When you create a class, VERSANT creates a special kind of object, called a "class object" or "schema object," that stores your data type definition in a database. You can define classes to contain any kind of data, including values, images, sounds, documents, or references to other objects. Only a very few data types are difficult to implement in object databases. For example, bitfields can cause problems in heterogeneous systems, and pointers to functions are difficult to implement although easy to avoid.

C++/VERSANT — Objects are defined in a class using normal C++ mechanisms. VERSANT creates for each class an associated runtime type identifier object that contains additional information needed by C++. This runtime type identifier object is an instance of the C++/VERSANT class PClass. Each instance object has an is_a pointer to its type identifier object in order to identify its class.
Versioned object To track the evolution of the states of an instance object, VERSANT allows you to convert an instance object to a "versioned object." There can be numerous versions of a particular instance object.

35

VERSANT Database Fundamentals Manual

Transient object A transient object exists only while the program that created it is running. Persistent object A "persistent object" is an object can be stored in a VERSANT database. Persistent objects must derive from the VERSANT PObject class. When a complex object is read from a database, only those portions of it which are examined by the user will actually be loaded into memory, allowing "large" objects to be lazily instantiated on a per object basis. Performance options are provided so that you can explicitly control how referenced objects are read in.

C++/VERSANT — Both transient and persistent objects are dereferenced with the same syntax.
Stand-alone Stand-alone object

C++/VERSANT — A stand-alone object is one created with the C++ new operator, with a C++/VERSANT new operator or function, or an object defined as a local or global variable.
Embedded object

C++/VERSANT — An embedded object is an object that is an attribute of another object.
Smart object A smart object automatically selects the correct version of an object based upon a pre-selected configuration.

36

VERSANT Database Fundamentals Manual

Object Elements
Although objects are used as if they were a single structure, the implementation of objects involves several discrete elements. Object attributes

C++/VERSANT — The parts of an object that store data and associations with other objects are called "attributes." An attribute is persistent when the object containing it is persistent. An attribute can be a literal whose elemental value is self-contained, another object with its own attributes, an object that is an array of other objects, or a reference to another object. Attributes are first defined in normal C++ class files. After class files have been compiled, attribute definitions are loaded into a database and stored in class objects. Actual data are stored in instance objects.
Object methods

C++/VERSANT — The parts of an object that store executable units of program code are called methods. Methods are defined and implemented in normal C++ class files. After the class files have been compiled, methods are linked with an application. C++/VERSANT Example — For example, consider a C++ class named Coord.

Attributes of class Coord are the coordinates x and y. Methods of class Coord are set(), which sets the values of the coordinates, get_x(), which returns the value of the x coordinate, and get_y(), which returns the value of the y coordinate.

37

VERSANT Database Fundamentals Manual

Object Characteristics
Following are characteristics of persistent objects. Object identity One of the strongest concepts in object technology is object identity, because it makes possible such features as persistent references to other objects and the ability to migrate objects among distributed databases without having to change code that accesses the objects. VERSANT assigns each persistent object a unique identifier called its logical object identifier or loid. Logical object identifiers are composed of two parts: a database identifier and an object identifier. The database identifier portion of a loid is an identifier for the creation database that is unique among all databases in a system of databases. This identifier is created by VERSANT when the database is created. To ensure that database identifiers are unique, all databases in a system of databases have their identifiers stored in a single database system file named osc-dbid. When you create a database, your system must be able to modify the system file, but once a database is created you do not need to be connected to a network to perform tasks such as creating or managing objects in a local database. The object identifier portion of a loid is an identifier that is unique within the creation database. This identifier is created by VERSANT when the object is created. Because the object portion of the identifier is based only upon other objects within the creation database, you only have to be connected to the creation database when you create an object. Because an object identifier is built upon a database identifier unique within a system of databases and an object identifier unique within a database, it is guaranteed to be unique among all objects in a system. The overhead in memory of a VERSANT object identifier, on 32-bit cpu architectures, is approximately twenty-four bytes per persistent object, and four bytes for a non-persistent object. A link requires eight bytes. For a particular database system, you can address 2^64 objects in 2^16 databases. Object migration The ability to migrate objects makes distributed databases practical. After an object has been created, you may want to migrate it in order to place it physically closer to where it is most often used, which will reduce network traffic, or migrate it because disk space is filling up on the machine containing the creation database. Object and database identifiers do not change when an object or database is moved or changed. Identifiers are never reused, even after an object or database has been deleted. This means that code that
38

VERSANT Database Fundamentals Manual

references an object does not have to be changed each time an object is migrated. Each persistent object must have a class object associated with it that contains its class definition. When you migrate an object to a new database, if it is not already defined in the target database, a copy of its class object is also migrated. Because migrating an object instance includes migration of its definition in a class object, a particular class object may be duplicated in numerous databases. However, once a class object has been migrated, it exists as an independent object in that database. This means that to use a migrated object, you do not have to be connected to its creation database. If classes of the same name are defined differently in different databases, an attempt to migrate an object with a different class definition will be automatically blocked. You can then use any of a variety of mechanisms, such as a "synchronize class" routine, to resolve the differing class definitions. Dynamic binding When you define a new class that specializes its base class, you may want to redefine methods, such as a "print yourself" method, for the new class. Inherited methods can be redefined in sub-classes. Polymorphism To use a method, you call an object method with a message. For a method to respond, the message must have both the correct name and the correct signature. The number and data types of the arguments for a method are called its signature. You can overload a method to work for several classes and a varying number of arguments; this is called polymorphism and can simplify control structures significantly. In effect, polymorphism binds a message to a particular method at run time in a manner similar to case statements. Situation modeling An important advantage of using the object model is its ability to model situations in a realistic manner than can be understood by others. Using classes to classify individual elements of a situation and then using embedded, inheritance, and reference relationships to relate classes to one another results in a model that directly reflects the real situation. This is much more understandable than a flat system of normalized tables whose logic must be reassembled each time they are used in each application that accesses them. Schema modification After you have completed a complex application, you will almost certainly want to extend or modify its underlying classes to accomplish new tasks. The set of object definitions associated with a particular database is called the "schema" of that database.
39

VERSANT Database Fundamentals Manual

You can add to and change the schema of a database at any time. In many cases, you will be able to redefine classes by extending them to hold additional data, perform new tasks, and perform existing tasks differently without changing applications that use the classes. Predefined types VERSANT predefines many elemental and class types that you can use with embedded, inheritance, and association relationships. The following types available in all interfaces. Vstr — A vstr provides low overhead, variable length storage for one or many elemental values. Link — A link stores a reference to another object. Link vstr — A link vstr provides variable length storage for one or many references to other objects.

C/VERSANT — C/VERSANT also predefines the following type.
List — A list provides ordered variable length storage.

C++/VERSANT — C++/VERSANT also predefines the following types.
Bi-link — A bi-link stores a bi-directional reference. Bi-link vstr — A bi-link vstr provides variable length storage for one or many bi-directional references. Array — An array is an ordered collection of elements accessed by an index which is an integer. Set — A set is an unordered collection of unique elements. Dictionary — A dictionary is a collection that maps keys to values. List — A list provides ordered variable length storage. Date and Time — Date and time attribute types. The C++/VERSANT interface also provides facilities to create the following types: Parameterized — Parameterized types allow single definitions for classes that differ only by the data type of their contents. This is useful for classes, such as sets, that have identical functionality and differ only in the data type of their contents. Run-time — Classes that are defined at run-time. Smart — Smart objects automatically select the correct version of an object based upon a pre-selected
40

VERSANT Database Fundamentals Manual

configuration. VERSANT also allows you to use third party class libraries to define your classes.

41

VERSANT Database Fundamentals Manual

Object Status
When you create or access a database object, VERSANT maintains information about its current status. Following is a list of the status information maintained about each object. Object transient, persistent status When you create an object, VERSANT notes whether it is transient or persistent. Within the scope of a transaction, transient objects are treated the same as persistent objects, but when you perform a commit, only persistent objects are saved to a database. Object lock status Locks provide access guarantees to objects. For example, a write lock guarantees that you are the sole user of an object, which is important if you want to update the object. Object dirty status When you change an object, you must mark it as "dirty," which means that it will be updated at the next commit. This improves performance significantly, because at the time of a commit VERSANT does not have to compare the contents of each object you have used with its original contents in order to determine which objects need to be updated. Object versioned status You may want to track the evolution of the states of an object over time. To track object states, you can convert regular, non-versioned objects into versioned objects. When a non-versioned object is updated, its old data is overwritten. When a versioned object is checked out for update, the old object is preserved and a new object is created with the new data. The new is called a "child" of the original "parent" object. Versioned objects that share the same parent are called "siblings." Each version of an object has a unique object identifier, a number, and a version status, such as transient, working or released. All versions of an object are maintained by VERSANT in a version graph. Versioned objects behave differently from non-versioned objects under certain circumstances, such as during a checkout and checkin. For example, versioned objects are checked out with a null lock and become new objects.

42

VERSANT Database Fundamentals Manual

Object configuration You can group specific versions of different objects into "configurations," and then automatically select the correct object versions using a "smart object." Object checkout status To improve workgroup functionality, an object can be checked out from a group database accessible to many users to a personal database accessible to only one user. When an object is checked out, a copy of it is made and placed into the personal database and a persistent lock is placed on the original object. This allows you to work on an object for an extended period of time without network traffic. Unless the object is a versioned object, the checkout copy in the personal database shares the same object identifier as the source object in the group database. This replication ends when the possibly changed object is checked back into the group database. Versioned objects become new objects when they are checked out and when they are checked in. When you checkout an object, you can set persistent object locks which will survive short transaction commits and specify various other options, such as a request to be notified if another user is trying to access the objects you have checked out. Object pin status

C/VERSANT and C++/VERSANT — To manage memory efficiently and to improve access to objects of current interest, VERSANT maintains an object cache in virtual memory that contains all the objects accessed during a transaction. An object in the cache can be "pinned," which means that it will not be swapped out of the object cache back to its source database. A pinned object is not guaranteed to be in process memory, just in virtual memory.
Normally, pinning occurs automatically when you access an object, but you can explicitly unpin objects if you are accessing a large number of objects and virtual memory is limited. VERSANT also allows you to set nested pin regions to make it easier to pin and unpin specific sets of objects.

43

VERSANT Database Fundamentals Manual

Object Relationships
Object embedded relationship

C++/VERSANT — An "embedded relationship" is created when you use an object as an attribute of another object. An embedded relationship can also be called a "contains-a" or "containment relationship." When you create instances, embedded objects are accessed via the containing object.
An object that contains an aggregation of embedded objects provides referential integrity and avoids orphaned data. Using embedded objects can improve performance, because access to an aggregation of objects is done in one step, and only one entity is locked. Embedding predefined types such as dates or custom designed sets can also save a lot of programming time. Some C++/VERSANT classes can be used only as embedded objects, while others can be used as stand-alone objects. Object inheritance relationship When you define objects, you can specify a hierarchical structure of base and derived classes. In this hierarchy, descendant objects "inherit" data and methods from their ancestors. This means that you can store data in an instance as if it had all of the attributes that are in its ancestors, and you can manipulate an instance as if it had all of the methods that are available to its ancestors. Inheritance is an efficient way to describe a situation: base classes describe once what is common to all of its derived classes, then each derived class describes only what is new or different about itself. Because derived classes inherit both attributes and methods, inheritance enables stable data and code definitions to be reused, extended, and customized. An inheritance relationship is called an "is-a" relationship, because the derived class is a special form of its base class.

C++/VERSANT — In C++, there can be two kinds of inheritance: single inheritance and multiple inheritance. Single inheritance describes an object related to ancestors in a stack structure. Multiple inheritance describes an object related to ancestors in a tree of stacks.
Object association relationship An important feature of the object model is the ability to associate objects that are logically related but that are of different types. The ability to associate objects allows you to create graph structured data relationships. For example, while inheritance is useful to define an employee as a kind of person, you must create an association to relate an employee to a department.

44

VERSANT Database Fundamentals Manual

C++/VERSANT — The association of objects is similar to using a C++ pointer from one object to another, assuming that both objects have been assigned a virtual memory address. However, pointers are not valid for objects in a database but not in memory, and pointers are unreliable for objects that are not pinned in virtual memory.
To create persistent database pointers, C++/VERSANT uses "links." Links are sometimes called "smart pointers," because they are valid regardless of the location of the object, whether in memory or in a database, and they remain valid even if you move the object from one database to another. The transparency of links is important, because it allows you to write code that does not depend upon the memory or database location of objects. Link relationships are called "has-a" relationships, because one object "has a" link to another object. There are several performance advantages to using links. Just as the fastest way to find an object in memory is to use a pointer, it is much faster to find an object in a database using a link rather than a query. This means you can move quickly among related objects by traversing the graph of relationships rather than performing repeated queries and joins. Links also improve performance because linked objects are retrieved only when you decide that you actually want the object by dereferencing the link. You can use either links or arrays of links as attributes. You can create one-to-one, one-to-many, many-to-one, and many-to-many associations using the predefined VERSANT link and link vstr data types. VERSANT also has data types for "bi-links," which provide referential integrity and cascaded deletes, and for containers, arrays, sets, lists, and dictionaries, which allow you to associate many objects into a single structure.

45

VERSANT Database Fundamentals Manual

Chapter 3: Sessions
This chapter explains basic session concepts. Session Boundaries ........................................................................................................................47 Session Memory Areas ...................................................................................................................48 Session Elements ...........................................................................................................................49 Session Types................................................................................................................................51 Units of Work ................................................................................................................................53 Session Operations ........................................................................................................................54

46

VERSANT Database Fundamentals Manual

Session Boundaries
Applications perform VERSANT work in sessions. You must start a session to use VERSANT databases, methods, data types, and persistent objects. The only exceptions are methods that set session and environment parameters. A process or thread can be in only one session at a time.

C++/VERSANT
When you are using C++/VERSANT, transient objects of VERSANT data types and transient objects of classes derived from PObject that were created before a session should not be modified in a session. Transient objects of VERSANT data types and transient objects of classes derived from PObject that were created or modified during a session should be deleted before the end of the session.

47

VERSANT Database Fundamentals Manual

Session Memory Areas
When you start a session, VERSANT creates the following session memory elements. The object cache, cache table, and session tables may be created in client machine memory. The server page cache is in shared memory on the machine containing the session database. All memory areas are maintained for you by VERSANT. Object cache An object cache in virtual memory improves access to objects used in a transaction. Object cache table A cached object descriptor table tracks the location of all objects referenced during a session. Session tables Various session information tables track your processes, connected databases, and long and short transactions. Server page cache Associated with the session database and each connection database is a page cache for recently accessed objects.

48

VERSANT Database Fundamentals Manual

Session Elements
The following are also associated with sessions. Session database A session database is used to manage short transactions that occur during a session and to coordinate two-phase commits. It serves as the target of checkouts and is the initial default database. Either a personal database or a group database can serve as a session database. Only one personal database can be accessed in a session, which must be the session database. More than one group database can be accessed from a session database. Specification of a session database does not change the database association of an object. For example, when you commit a long transaction while ending a session, objects are returned to their source databases regardless of which session database you are using. To change the database used as the session database, you must end the session and start a new session. Session name The session name is used as the name of the short transactions that occur during the session. Default database A database designated as the default database is the location of new persistent objects and is used by many functions when a null database name is specified as a parameter. Initially the default database is the session database, but you can change the default after a session has started. Connected databases Once a session has started, you can connect to other databases. Each database connection starts a new server process on the database machine. Short transaction When you start a "standard" session, VERSANT begins keeping track of your activities in a short transaction. Long transaction A session is always in a single long transaction. A long transaction object in the session database tracks
49

VERSANT Database Fundamentals Manual

checked-out objects and persistent locks.

50

VERSANT Database Fundamentals Manual

Session Types
When you begin a session, depending upon your interface language, you may be able to specify the kind of session that you want. VERSANT provides the following session options. Standard session In a standard session, you are always in a short transaction and in a long transaction, and you are using the standard lock model. Almost all tasks can be performed using short transactions with commits, checkpoint commits, rollbacks, and savepoints. The standard VERSANT locking model satisfies most concurrency requirements. If you do not make a specification for session type when you start a session, you will start a standard session. Shared session In a shared session, you can use multiple processes, because the object cache is created in shared memory. A shared session is useful if you have a parallel processing machine or if it is likely that related transactions may encounter delays, such as waits for locks, user input, or a printing activity. In a shared session, when one process is delayed, others can continue. Each time an application process joins a shared session, a corresponding server process will automatically be started for each existing database connection (including the connection to the session database), and if any application process in the session makes a new database connection, connections are made and server processes are started as needed for all other processes in the session. Multiple threads in a session are usually more efficient than multiple processes, so using multiple threads is recommended over shared sessions. See the chapter "Multiple Processes in a Single Session" for more information.

51

VERSANT Database Fundamentals Manual

Multiple threads and multiple sessions You can start a session in which you can place one or more threads. If you start this kind of session, you can also start additional sessions, and each of the additional sessions can have zero or many threads in it. See the chapter "Multiple Thread(s) in Multiple Session(s)" for more information. Shared session with high performance option You can start a shared session in which no latches are held on the object cache when a process reads or writes to a database. During this time, other processes can continue to locate and process objects in the cache at memory dereference speed, although you will get an error if more than one process tries to read or write to a database at the same time. This option is called the "single writer / multiple reader" option. Optimistic locking session An optimistic locking session suppresses object swapping, prevents automatic lock upgrades, and provides automatic collision notification. See the chapter "Optimistic Locking" for more information.

52

VERSANT Database Fundamentals Manual

Units of Work
Following is the hierarchy of possible VERSANT units of work in various kinds of sessions. (Some interfaces do not allow all types of sessions, such as shared or thread sessions.)
Long transaction Standard session Short transaction Savepoint Standard session with threads Short transaction Savepoint Shared session with multiple processes Short transaction Savepoint

Many long transactions can co-exist and do not depend on the kind of session that you start. Sessions can be a sequence of none to many. Short transactions are a sequence of one to many within a session. Savepoints are a sequence of none to many within a short transaction. See also the chapters "Short Transactions" and "Long Transactions."

53

VERSANT Database Fundamentals Manual

Session Operations
Begin session Start a session, start a short transaction, and start or join a long transaction. c c++ o_beginsession() beginsession()

End session End a session, commit the current short transaction, disconnect the application process from all databases, close all session memory workspaces, and commit, rollback, or continue the current long transaction. c c++ o_endsession() endsession()

End process and end session End a session if it has not already ended, terminate the application process, and either commit or roll back the current short transaction, depending upon the option supplied. c c++ o_exit() exit()

54

VERSANT Database Fundamentals Manual

Chapter 4: Transactions
Short Transactions .........................................................................................................................56 Short Transaction Description ......................................................................................................56 Short Transaction Actions............................................................................................................57 Short Transaction Usage Notes ....................................................................................................59 Short Transaction Hierarchy.........................................................................................................60 Short Transaction Effect on Memory .............................................................................................60 Long Transactions ..........................................................................................................................62 Long Transaction Description.......................................................................................................62 Long Transaction Actions ............................................................................................................62 Long Transaction Usage ..............................................................................................................63

55

VERSANT Database Fundamentals Manual

Short Transactions
Short Transaction Description
A short transaction is a logical unit of work whose results are either saved or abandoned as a group. Transactions are an essential database concept, because they ensure that data is always in a known state, even in a distributed database environment. As soon as you start a session, VERSANT begins keeping track of your activities in two kinds of transactions, a short transaction and a long transaction. For information about long transactions, see the chapter "Long Transaction". Short transactions are: Atomic — When a short transaction ends, the results of all actions taken in the transaction are either saved or abandoned. This is an important database feature, because it ensures that data is always in a consistent and known state. Durable — Results are either saved permanently or abandoned permanently: no further undo or redo operations are possible. Independent — When you are operating on locked objects in a transaction, no other user can intrude upon your work. While in a transaction, you can operate on your objects as if you were the sole user of a database. Coordinated — Objects in a transaction are locked, which means that your work is coordinated with other users in a workgroup environment. Distributed — A two phase commit protocol ensures that data is always in a known state even when you are working with objects in numerous databases in a distributed database environment. Ever-present — You are always in a short transaction. When you end a short transaction, another is automatically started for you. If you are an advanced user, you may want to create special kinds of short transactions. If you have a special need you can start sessions in which you can use multiple processes in a transaction. A session is also a unit of work. For information about sessions, see the chapter "Session."

56

VERSANT Database Fundamentals Manual

Short Transaction Actions
Commit short transaction A commit saves your actions to the databases involved and releases short locks. A commit also releases objects from cache memory, erases all savepoints, asserts persistent locks, and starts a new short transaction. A commit makes no changes to transient objects. Changes made in a short transaction are not visible to other users until you commit them. This means that others cannot be confused by seeing partial changes. However, objects that have been flushed to their database (by swapping, queries, or deletions) will be visible to users using null locks in dirty reads. c c++ o_xact() commit() xact()

Checkpoint commit short transaction A checkpoint commit performs a save and holds object locks. A checkpoint commit also maintains objects in cache memory, erases all savepoints, asserts persistent locks, and starts a new short transaction. A checkpoint commit makes no changes to transient objects. Changes made in a short transaction are not visible to other users until you commit them. This means that others cannot be confused by seeing partial changes if they are using read locks. However, objects that have been flushed to their database (by swapping, queries, or deletions) will be visible to users using null locks in dirty reads. c c++ o_xact() checkpointcommit() xact()

Rollback short transaction A rollback abandons your actions, releases short locks, and restores databases to conditions at the last commit or checkpoint commit. A rollback also releases objects from cache memory, erases all savepoints, and starts a new short transaction. A rollback makes no changes to transient objects. If your application or machine crashes, VERSANT will automatically roll back the current incomplete short transaction.

57

VERSANT Database Fundamentals Manual

c c++

o_xact() rollback() xact()

Begin session Beginning a session starts a short transaction. During a session, you are always in a short transaction. c c++ o_beginsession() beginsession()

End session Ending a session performs a short transaction commit. c c++ o_endsession() endsession()

Set savepoint Setting a savepoint creates a snapshot of database conditions to which you can selectively return without ending the short transaction. Setting a savepoint makes no changes to databases, locks, transient objects, or the memory cache. When a savepoint places a record of current conditions in the database log, changes to an object are visible to other users if they access the object with a null lock in a dirty read. You can set as many savepoints as you want in a normal short transaction. Using savepoints is a way of working down a set of instructions toward a solution and then backtracking if some sub-set of the solution fails. Savepoints are not compatible with optimistic locking, however, because setting a savepoint flushes objects to their databases, which resets locks. c c++ o_savepoint() savepoint()

Undo to savepoint Undoing a savepoint returns database conditions to the immediately previous savepoint; if there is no immediately previous savepoint, conditions will be restored to those that existed at the last commit. Undoing a savepoint makes no changes to databases, locks, or transient objects, but it does invalidate the object memory cache.

58

VERSANT Database Fundamentals Manual

c c++

o_undosavepoint() undosavepoint()

Short Transaction Usage Notes
Following are usage notes related to short transactions. Turn logging on To use short transactions in your application, you must enable logging in your database. See the VERSANT Database Administration Manual for information on turning logging on and off. Turn locking on To use short locking in your application, you must enable locking. See the VERSANT Database Administration Manual for information on turning locking on and off. Keep them short Keep short transactions short, because locks held by transactions block other users and work not committed will be lost if the application or machine crashes. Commit when states are consistent Commit a short transaction only when the states of the objects you are working with are internally consistent. Build in short transactions Build short transactions into your application from the beginning. Transactions are essential to data consistency and workgroup concurrency, yet they can be hard to retrofit into an application as they are a major structural element. Do not commit with a link to a transient object If you have an attribute of a persistent object that contains a link, link vstr, bilink, or bilink vstr, the attribute cannot contain a link to a transient object at the time of a commit.

59

VERSANT Database Fundamentals Manual

Short Transaction Hierarchy
The short transaction hierarchy is:
Session Short transaction Savepoint

For example:

Changes in transactions 1, 3, and 4 are committed to the database, while changes made in transaction 2 are discarded.

Short Transaction Effect on Memory
Memory effects of a short transaction — After a short transaction routine has executed, the following effects take place on memory:

Memory effects of a short transaction Cache and cache table Invalidate object cache Invalidate codtable

undo savepoint yes no

rollback

checkpoint commit no no

commit

end session yes yes

yes no

yes no

60

VERSANT Database Fundamentals Manual

Afterwards for C Can use o_object in a variable Can use a vstr Can use pointer to persistent obj Afterwards for C++ Can use link held in a variable Can use transient object created in a session modified in a session Can use pointer to persistent obj

yes yes no

yes no no

yes yes yes

yes no no

no no no

yes yes yes no

yes yes yes no

yes yes yes yes

yes yes yes no

no no no no

61

VERSANT Database Fundamentals Manual

Long Transactions
Long Transaction Description
To improve performance in workgroup settings, VERSANT allows you to checkout objects to a personal database. Long transactions are a mechanism to track checked out objects and persistent locks. Each time you check out a non-versioned object with a read or write lock, that object becomes associated with the current long transaction. When you are done with the checked out objects, you can return them to their source databases in a single step by ending the long transaction. When non-versioned objects are checked out with a read or write lock, object identity is maintained. This means that links to checked out objects are still valid. If a linked object is also checked out with an object containing the link, the link will point to the object in the checkout database. If the linked object is not checked out, the link will point to the object in its original database. As soon as you start a session, you are in a long transaction.

Long Transaction Actions
Long transactions are defined by beginning and ending a database session. When you start a session, you can start a new long transaction by specifying a new long transaction name or join an existing long transaction by specifying the name of an existing long transaction. If you do not specify a long transaction name, then a default name is used and you either create or join a long transaction with the default name. The default name is your login user name. You can create numerous long transactions to track differing sets of checked out objects. A session takes place within a single long transaction that can last any length of time. Committing, rolling back, or continuing a long transaction has no effect on the tracking of checked out objects and persistent locks on objects not associated with that long transaction. See the chapter "Moving Objects" for information about checkins and checkouts.

62

VERSANT Database Fundamentals Manual

Begin or join long transaction When you start a session, you can begin or join a long transaction. c c++ o_beginsession() beginsession()

Commit long transaction A long transaction commit returns write-locked, non-versioned objects associated with that long transaction to their source database and drops the copies made in the personal database used for the checkout. A long transaction commit also drops all persistent locks on non-versioned objects that were set during the long transaction, including those persistent locks set explicitly without making a checkout. c c++ o_endsession() endsession()

Rollback long transaction A long transaction rollback drops all checked out, non-versioned objects associated with that long transaction from the checkout database and leaves the checked out objects in their current state in their source databases. A long transaction rollback also drops all persistent locks set during the long transaction, including those persistent locks set explicitly without making a checkout. c c++ o_endsession() endsession()

Continue long transaction Continuing a long transaction means that you can rejoin it at a later time with no changes to persistent locks or to the checkout status of objects associated with the long transaction. c c++ o_endsession() endsession()

Long Transaction Usage
You must access long transactions from your original session database. Information about a long transaction, including the objects associated with the long transaction and their source databases, are stored and maintained for you by VERSANT in a long transaction object. This long transaction object is created and updated in the database used as a session database. Thus, access to a particular long transaction depends on your choice of a session database.

63

VERSANT Database Fundamentals Manual

You can override long transactions. You do not have to end a long transaction to check in objects. You can override long transaction tracking of objects with an explicit checkin of particular objects. However, you cannot check in objects not associated with the current long transaction. If an object checked out in a long transaction has been previously, explicitly checked in before the long transaction ends, then ending the long transaction does not change the object state but it does release all persistent locks. You must be connected to all source databases. Committing a long transaction will fail if you are not connected to all source databases for the checked-out objects. You can create any number of long transactions. You can define any number of long transactions to keep track of discrete sets of objects. These long transactions can be in the same or different personal databases. Once you have created multiple, named long transactions, you can move from one long transaction to another within an application by stopping the current database session and starting a new session. You must keep track of the long transaction names you have used. While in a session, you can work with all objects that have been checked out to your current session database in all of the long transactions you have created, although accessing an object in a long transaction other than the one in which it was checked out does not change its association with the long transaction used to check it out. When you end a long transaction, only the objects associated with that long transaction are returned to their source databases and have their persistent locks released. Successive sessions in a long transaction can be started with any session option that is valid for your platform and interface, such as the nestable transaction, shared object cache, and custom locking options. You cannot access a checked out object from its source database. Once you have checked out an object with a persistent read or write lock in a long transaction, you cannot access it from the target/session database in its source database in either that long transaction or in any other long transaction, unless it is a versioned object. If you have checked an object out with a null lock, you can still access it in its source database, because a checkout with a null lock creates a new object with its own identity and existence.

64

VERSANT Database Fundamentals Manual

You do not have to turn logging on. Long transaction tracking of checked-out objects occurs whether logging is on or off in either source or target databases. However, changes to a database cannot be rolled back if logging is off under the following conditions: • If logging is off in the session database:

If a commit fails after a checkout, the status of long transaction tracking is indeterminate; copies of the checked-out objects may or may not have been created in the session database. If a commit fails after a checkin, the status of objects returned by the checkin is indeterminate; the copies in the session database may or may not have been deleted. • If logging is off in the source database:

If a commit fails after a checkout, the status of persistent locks is indeterminate; they may or may not have been set. If a commit fails after a checkin, the status of objects being returned by the checkin is indeterminate; the original objects may or may not have been updated to the states of the checked-out objects. If your personal database crashes, persistent locks in source databases are maintained. During recovery after a crash, if logging was on, long transactions are reconstructed, and objects are restored to their state at the last short commit. If you are working on checked out objects in a personal database and a group database crashes, you can continue to work on your checked-out objects. When the group database recovers, it remembers which objects you have checked out and what locks you placed on them.

65

VERSANT Database Fundamentals Manual

Chapter 5: Locks
Short Locks ...................................................................................................................................67 Lock Overview ...........................................................................................................................67 Locks and Transactions ...............................................................................................................67 Short Lock Features ....................................................................................................................68 Short Lock Types........................................................................................................................69 Short Lock Interactions................................................................................................................70 Short Lock Actions......................................................................................................................72 Short Lock Protocol ....................................................................................................................75 Short Locks and Queries..............................................................................................................78 Short Intention Lock Description ..................................................................................................79 Short Intention Lock Mode ..........................................................................................................80 Short Lock Precedence ...............................................................................................................81 Short Lock Interactions................................................................................................................82 Short Locks and the First Instance.................................................................................................83 Persistent Locks .............................................................................................................................85 Persistent Lock Description..........................................................................................................85 Persistent Lock Mode .................................................................................................................85 Persistent Lock Level...................................................................................................................87 Persistent Lock Queuing..............................................................................................................87 Persistent Lock Event Notification .................................................................................................88 Persistent Lock Precedence .........................................................................................................90 Persistent Lock Request Handling.................................................................................................90 Persistent Lock Actions ...............................................................................................................93

66

VERSANT Database Fundamentals Manual

Short Locks
Lock Overview
Locks provide guarantees which allow multiple processes to access the same objects in the same database at the same time in a cooperative, controlled, and predictable manner. If you were to be the sole user of a database, you would not have to be concerned with locks. And, at times when you are the sole user of a database, you may want to turn locking off for the database and ignore locks entirely. However, locks are essential in a multi-user environment.

Locks and Transactions
Locks and transactions are conceptually related. Short locks and short transactions Short transactions are, by definition, units of work in which concurrency is provided by short locks. Typically, for concurrency reasons, short locks are held for short amounts of time. Short locks are released when a short transaction ends with a commit or rollback. Accordingly, for convenience in managing short locks, short transactions typically define units of work that take a short amount of time, such as seconds or minutes. However, since VERSANT provides mechanisms for upgrading and downgrading locks on specific objects and for writing specific objects to a database, "short" transactions do not have to be short. Ending a session also ends the current short transaction (you can specify ending a session with either a short transaction commit or rollback.) A short lock does not survive a system disruption. Persistent locks and long transactions Long transactions manage checkin/checkout operations that take a long amount of time, such as many minutes, hours, days, or weeks. A persistent or long lock manages concurrency during a long transaction. A persistent lock has all the features of a short lock plus added functionality, such as the ability to survive the end of a short transaction, database session, and a system disruption. Persistent locks are not tightly coupled with long transaction checkouts. You can also set a persistent lock if you want to use an object during an extended period of time without checking an object out.

67

VERSANT Database Fundamentals Manual

For more information on persistent locks, see the section "Persistent Lock."

Short Lock Features
Following are features of VERSANT locks. A lock provides an access guarantee. A lock on an object provides an access guarantee. The access guarantee is provided by blocking certain kinds of actions by other users. Locks are applied to objects. To maximize concurrency, locks are applied at the object level. Any object can be locked. Locks can be set on all kinds of objects: instance objects, versioned objects, and class objects. Locking a class object locks all objects of the class. Placing a lock on a class object has the effect of placing the same lock on all instances of a class. This is far faster than retrieving all objects of a class and placing individual locks on each object. Linked objects are not locked. Locking an object does not lock objects which are the targets of links in the locked object. An object can have only one lock in a transaction. In a particular transaction, an object can have only one lock on it at a time. If you separately request different locks on the same object, the lock placed depends upon the relative precedence of the locks. For example, if you request a read lock on an object for which you already hold a write lock, the read lock request is ignored; if you request a write lock on an object for which you already hold a read lock, the read lock is replaced by a write lock. Locks have precedence. The precedence of locks is: write > update > read > null. An exception to this rule occurs if you are using multiple processes in the same session. In this case, different processes can place different locks if they are compatible. For example, different processes can request and receive a read lock and an update lock on the same object, but the net effect is the same to outside users: the highest lock prevails.

68

VERSANT Database Fundamentals Manual

Locking an object also prevents the class object from being changed. When you place a read, update, or write lock, VERSANT internally places a special kind of lock on the class object which prevents it from being changed while the instance object is locked. You can turn locks off. You can enable or disable short locks. two-phase Strict two-phase locking is used. VERSANT uses a strict, two-phase locking strategy. By "strict" is meant that locks are set before work starts rather than at commit time when locks might not be available. Strict locking prevents other applications from modifying an object while you are using it and is the appropriate strategy in a multiple user environment. By "two-phase" is meant that all locks are gathered in one phase and then released in a second phase, when the transaction ends. Implicit locking is used. By default, VERSANT uses an "implicit" locking strategy in which methods automatically obtain locks as needed. For example, marking an object as dirty automatically obtains a write lock. You can override the VERSANT implicit locking strategy in several ways. You can explicitly upgrade locks, change the default lock, and/or change the lock wait time.

Short Lock Types
Following are the types of short lock modes and their access guarantees. Short write lock A write lock guarantees that you are the sole user of an object and that you are looking at the current state of an object. It is useful when you want to update an object. A write lock provides its guarantee by blocking all other requests for a write, read, or update lock on a particular object. A request for a write lock is blocked if the object already has a read or update lock. c c++ WLOCK WLOCK

Short update lock An update lock allows you to read an object and get the next available write lock on it. It is useful if you want to look at an object now while knowing that you will later want to update it. An update lock provides its guarantee by blocking all other requests for a write or update lock. It does not block other requests for a read lock, but if another user tries to change a read lock to a write lock, that request may cause a deadlock error that they must handle or have their application terminated. A request for an update lock is
69

VERSANT Database Fundamentals Manual

blocked if the object already has a write or update lock. c c++ ULOCK ULOCK

For a further explanation of the importance and usage of update locks, see the following section "Locking Protocol." Short read lock A read lock guarantees that an object will not be changed while you are looking at it. It is useful when you want to look at an object but not change it. A read lock provides its guarantee by blocking all other requests for a write lock. It does not block other requests for a read or update lock. A request for a read lock is blocked if the object already has a write lock. c c++ RLOCK RLOCK

Short null lock A null lock, also called a "snapshot" lock, provides no access guarantees and, strictly speaking, is not a lock at all. Specifying a null lock is useful when you want to look at the current state of an object without placing a lock or waiting for other locks to be released. Looking at the current state of an object without placing a lock is sometimes called a "dirty read," because there are no guarantees that the object will not be changed while you are looking at it. That is, a null lock does not block other requests for a write, read, or update lock. A request for a null lock is never blocked. c c++ NOLOCK NOLOCK

Short Lock Interactions
Blocking of locks The following summarizes how short locks interact.

70

VERSANT Database Fundamentals Manual

When you request a short lock, the system immediately tries to obtain it. A short lock is granted on an object if the following conditions are true: • • There are no incompatible short locks. For example, a read lock is not granted on an object that already has a write lock. There are no persistent locks with an incompatible lock mode. Since the lock mode of a persistent lock specifies a matching short lock, this condition is usually similar to the first condition. It differs if you have turned locking off for a database, since turning locking off for a database disables short locks but has no effect on persistent locks. This means, for example, that if locking has been turned off, you will not be able to set a short write lock, but you will be able to set a persistent write lock which will have the same effect as a short write lock. If your request succeeds, the system places your short lock immediately. If your request for a short lock is blocked by an incompatible short or persistent lock, your application pauses either until the object becomes available or until your request times out. If your request times out, you will receive a "lock timeout" error. The length of time a request waits is determined by the value of the lock_wait_timeout parameter in the Server Process Profile. Deadlocks Potential deadlocks are detected immediately and a "would-cause-deadlock" error is sent to the user creating the potential deadlock. For example, if two users have read locks on an object and then both request a write lock, the first user to request a write lock is blocked, and the second user receives a "would-cause-deadlock" error message. (In this case, the first user would receive the lock if a lock wait time-out did not occur.) VERSANT directly handles complex, single-database deadlocks with any number of clients and any number of locked objects. (An example of a "complex" deadlock is "A waiting for B waiting for C waiting for D waiting for A".) VERSANT uses timeout mechanisms to detect multiple database deadlocks.

71

VERSANT Database Fundamentals Manual

Short Lock Actions
Set short lock explicitly The following set a short lock explicitly. c c++ o_acquireslock() o_upgradelock() acquireslock() upgradelock()

set short lock upgrade lock set short lock upgrade lock

Set short lock implicitly The following set a short lock implicitly or allow you to specify a short lock in a parameter. c o_acquireilock() o_acquireplock() o_checkin() o_checkinreturnobjs() o_createvsn() o_deleteobj() o_deletevsn() o_dropattr() o_dropclass() o_dropinst() o_gcheckout() o_gdeleteobjs() o_getclosure() o_greadobjs() o_locateobj() o_locatevsn() o_new_attr() o_pathpcheckout() o_pcheckout() o_preptochange() o_preptoversion() o_refreshobj() o_refreshobjs() o_renameattr() o_select() o_setdirty() (type*)() acquireilock()

set intention lock set persistent lock check in objects check in objects create version delete object delete version drop attribute drop class drop instances check out objects delete objects find object and linked objects get objects get object get version create attribute find and checkout object find and checkout object set object dirty create versioned object refresh object refresh objects rename attribute find object dirty object cast link set intention lock

c++

72

VERSANT Database Fundamentals Manual

acquireplock() checkin() createvsn() delete deleteobj() deletevsn() dirty() gcheckout() gdeleteobjs() getclosure() greadobjs() locateobj() locatevsn() operator*() operator ->() operator delete pcheckout() preptochange() preptoversion() refreshobj() refreshobjs() select() setdirty()

set persistent lock check in object create version delete object delete object delete version set object dirty check out objects delete objects find object and linked objects get objects get object get version dereference link or pointer dereference link or pointer delete object find and checkout object set object dirty create versioned object refresh object refresh objects find object dirty object

Release short lock explicitly The following release short locks explicitly. c c++ o_downgradelock() downgradelock()

downgrade lock downgrade lock

Release short lock implicitly The following release short locks implicitly. c o_endsession() o_endtransaction() o_exit() o_xact() o_xactwithvstr()

end session commit or rollback exit process commit or rollback commit or rollback

73

VERSANT Database Fundamentals Manual

c++

abort() commit() endsession() exit() rollback() xact() xactwithvstr()

rollback commit end session exit process rollback commit or rollback commit or rollback

74

VERSANT Database Fundamentals Manual

Get default short lock c++ get_default_lock()

get default lock

Set default short lock When a session begins, the default short lock is a read lock. You can reset the default. c c++ o_beginsession() o_setdefaultlock() beginsession() set_default_lock()

begin session set default lock begin session set default lock

No effect None of the following affects short locks.

checkpoint commit pin object release object set savepoint undo savepoint unpin object write objects zap object cache

Short Lock Protocol
The goal of a locking protocol is to maximize concurrent use of objects. Locking protocols are voluntary, but if not followed by all users, unexpected situations may occur. A "deadlock" occurs when two transactions both hold read locks on the same object, both transactions then attempt to upgrade their locks to a write lock, and neither transaction can continue because both are waiting for the other to release their read lock. To avoid deadlocks and maximize concurrency, the following voluntary locking protocol is recommended: • If you want to snapshot read the current state of an object, then request a null lock. You will then get the object with no waiting and no blocking. Of course, the state of the object you get may become obsolete almost immediately. Use a read lock for objects that you know you do not want to modify. This allows others also to read the object.
75



VERSANT Database Fundamentals Manual



Use an update lock to read objects that you may later modify. This allows others also to read the object. If you decide to change the object, then request a write lock at that time. This keeps your write lock as short as possible. Never upgrade directly from a read to a write lock, because this can create a deadlock situation. Also, do not upgrade from a read lock to an update lock: get an update lock right from the beginning.



C++ — Dirtying an object is the same as requesting a write lock.
• • If you want to immediately change an object, then request a write lock from the beginning. If multiple applications are accessing the same group of objects, then you might also want to develop a protocol in which the different applications and/or transactions lock objects in the same order. The idea is to avoid a situation where one application asks for its locks starting with the beginning of a list of objects and another application asks for its locks starting with the end of the same list of objects (in which case, both applications would get some of the objects needed, but both would be blocked from getting all needed objects.)

Following are examples of typical usage of short locks. Example using a write lock Time 1 — Other users have a read lock on an instance. Time 2 — You want to update the same instance, so you ask for a write lock on it. The request is blocked and your application waits until the request can be granted or the request times out. Time 3 — Other users release their read locks by committing or rolling back their transactions. Time 4 — If your request has not timed out, your application resumes, and you obtain a write lock on that instance. Time 5 — You change the instance. Time 6 — You commit the change and release the write lock.

76

VERSANT Database Fundamentals Manual

Example using a read lock Time 1 — Someone has a write lock on an instance of a class, and many others have read locks on other instances of the same class. Time 2 — You want to create a report using the latest state of all objects at a particular moment in time. You request a read lock on the class object, but your request is blocked by the write lock on one instance of the class. Your application waits until the request can be granted or until the request times out. If the request times out, if you are creating a report, you might want to consider asking for a null lock on the instances to gain immediate access, although you would not be guaranteed to be looking at the latest state of the objects. You may also get an inconsistent set of objects. Time 3 — The user with a write lock on the instance executes a commit, which releases the write lock. Time 4 — If your request has not timed out, your read lock on the class object is now granted and coexists with other read locks on instances of that class. This means that no other user can modify any instance of the class. Time 5 — You can now print your report knowing that you are dealing with the latest state of all objects at that moment in time. Example using an update lock Time 1 — Numerous users are using a particular object, and they all have read locks on that object. But everyone has decided to follow recommended locking protocol for updates. Time 2 — Someone decides to first read and then update an object and requests an update lock. The request is granted even though other users also have read locks. Time 3 — You decide that you want to read and then update the same object, so you request an update lock. The request is blocked because an update lock already exists on that object. Your application waits. Time 4 — The first user requests a write lock. This lock upgrade request is blocked by existing read locks by other users. Time 5 — Other users with read locks finish and the user with the update lock gets a write lock. Time 6 — The other user finishes, and the object becomes available. If your request has not timed out, your application resumes and acquires an update lock. You are now guaranteed to be the next person to get a write lock on that object. Example that violates locking protocol The following example illustrates lock interactions and lock precedences. In the example, "You" and "UserB"
77

VERSANT Database Fundamentals Manual

both try to use the same object. In the example, even though you follow the recommended protocol, your work is disrupted because "UserB" does not follow the recommended protocol. Time 1 You have done nothing yet. UserB requests a read lock. UserB gets a read lock on the object. Time 2 You request an update lock. UserB still has a read lock. You get the update lock. Time 3 You have an update lock. UserB requests a write lock in violation of protocol. UserB waits because you have an update lock. Time 4 You request an upgrade to a write lock per recommended protocol. UserB continues to wait for a write lock. You get a "would cause deadlock" error, because two users are now waiting for a write lock. Time 5 Unless you handled the error and rolled back your transaction, your application continues to get a "would cause deadlock" error. Even though you followed the recommended protocol, UserB gets the write lock and continues. The recommended protocol is for UserB to request an update lock at Time 1.

Short Locks and Queries
A query will return an array containing links to the returned objects. When you dereference an object in the array and bring it into memory, the default lock will be set on the object.

78

VERSANT Database Fundamentals Manual

Depending on your interface language, there may be several forms of a select routine. Some will set the default lock on a class, and others will let you set an instance and/or class lock. You can set an inheritance flag in a select statement. If set to TRUE, the inheritance flag will cause the query to evaluate instances of both the specified class and also its subclasses. If you do set the inheritance flag, your choice of short lock will be set on both the class object of the query class and on the class object of each subclass instance returned by the query. If you want to lock all objects of the classes involved in the query, then specify a read or write lock in the query method. The effect will be the same as setting a read or write lock on all instances of the class and subclasses involved in the query, although, to improve performance, VERSANT actually only sets a read or write lock on the class objects for the instances returned. If you do not want to lock objects returned by the query until you dereference them, then do not specify a short lock mode. In that case, VERSANT will set a special kind of read lock, called an "intention read lock", only on the class object. The effect is to prevent the class objects from being changed while you are looking at their instances. If you have specified either an intention lock or have specified a null lock in a query statement, then you must place instance locks separately, which will be done automatically when you dereference the links. You do not need to know about intention locks unless you have special concurrency needs, because VERSANT automatically sets them on class objects whenever you set a lock on an instance object.

Short Intention Lock Description
This section explains intention locks. This is a topic you do not need to understand in order to use VERSANT. Intention locks are relevant only to class objects. The purpose of intention locks is to prevent changes to class objects while you are using an instance of the class. If your concurrency needs are unusual, then you may need to know about intention locks. You can place a normal or intention lock on a class object. Intention locks have the same effect on a class object that a normal lock has on an instance object, except that intention locks do not block one another. For example, an intention read lock on a class object prevents it from changing, but an intention read lock does not block an intention write lock. To maximize access to objects, an intention lock on a class object has no direct effect on instance objects. For example, an intention read lock on a class object does not block a write lock on an instance of that class. However, intention locks on class objects have an important indirect effect on instances, because to place a lock on an instance, a corresponding intention lock must also be set on the class object. Intention locks are set implicitly on class objects when you request a lock on an instance. For example, if you set a read lock on an object, VERSANT will set an intention read lock on the class object.

79

VERSANT Database Fundamentals Manual

If you use a query routine without specifying a lock mode argument, then the intention lock equivalent of the current default short lock is placed on the class objects for the instances returned. You should not set intention locks on instances. Although setting an intention lock has the same effect as a normal lock, this is not good practice. However, as soon as you try to do something meaningful, such as using the "get attribute" routine in C/VERSANT or dereference an object in C++/VERSANT, an appropriate lock is set.

Short Intention Lock Mode
VERSANT defines the following intention lock modes. Intention read lock An intention read lock on a class object prevents it from being changed. An intention read lock on a class object is compatible with an intention write lock on the class, and a write lock on an instance of the class. An intention read lock is useful if you want to prevent others from changing a class object while you are using instances of the class. An intention read lock is set implicitly by VERSANT on a class object when you request a read lock of an instance of the class. A request for an intention read lock on a class object is blocked only if it has a write lock. If you have an intention read lock on a class object, other users can still use instances of the class in a normal manner. They will also still be able to read the class object. The terms "intention read lock" and "intention share lock" are synonymous. c c++ IRLOCK IRLOCK

Intention write lock An intention write lock on a class object prevents other users from reading or updating it but allows them to use instances of the class. An intention write lock is useful when you want to prevent the class object from being changed or read. An intention write lock is set implicitly by VERSANT on a class object when you request a write lock on an instance of the class. A request for an intention write lock on a class object is blocked if it has a read, update, or write lock. It will not be blocked by another intention read or intention write lock.

80

VERSANT Database Fundamentals Manual

The terms "intention write lock" and "intention exclusive lock" are synonymous. c c++ IWLOCK IWLOCK

Read with intention to write lock A read with intention to write lock prevents a class object from being changed and has the same effect as placing read locks on all instances of the class. The terms "read with intention to write lock" and "share with intention exclusive lock" are synonymous. c++ c RIWLOCK RIWLOCK

Short Lock Precedence
The following shows lock precedence for both normal locks and intention locks. A write lock, at the top, has the highest precedence. A null lock has the lowest precedence.

81

VERSANT Database Fundamentals Manual

Short Lock Interactions
A lock provides a guarantee for a specific set of actions. To provide their guarantees, certain kinds of locks block other locks. For example, a write lock blocks a read lock, so that the process with the write lock is the sole user of the object. There can be two kinds of lock interactions: Interactions of normal locks Interactions of normal locks occur when a process requests a lock on a object that already has a lock: to be granted, the guarantees of the new lock must be compatible with the guarantees of any existing locks. These interactions are the same for both instance and class objects. Interactions of normal and intention locks Interactions of normal and intention locks occur when a process requests a lock on an instance and the system then attempts to place a matching intention lock on its class object: to be granted, the guarantees of the new intention lock must be compatible with the guarantees of any existing locks. The interactions of normal locks are relatively straightforward. For example, multiple read locks on the same object are compatible, but an object can have only one write lock. The interactions of normal and intention locks are more logically indirect. Because instance locks cause class object intention locks: • A lock on an instance object can block a request for a lock on a class object. For example, a read lock on an instance of a class blocks a request for a write lock on a class object, because a read lock on an instance also sets an intention read lock on the class object, and an intention read lock blocks a write lock. • A lock on a class object can block a request for a lock on an instance object. For example, a write lock on a class object blocks a read lock on an instance of the class because to get a read lock on an instance, you must also get an intention read lock on the class object. However, a write lock blocks an intention read lock. This behavior means that • • The definition of a class cannot change while an object is locked. Locking a class object with a normal, non-intention lock has the effect of locking all instances of a class.

82

VERSANT Database Fundamentals Manual

Locks interact in the following ways. write lock read/intention lock write Blocks write, read/intention write, intention write, update, read, intention read Blocks write, read/intention write, intention write, update, and read locks. Blocks write, read/intention write, update, and read locks. Blocks write, read/intention write, intention write, and update locks. Blocks write, read/intention write, and intention write locks. Blocks write lock. Blocks nothing.

intention write lock update lock read lock intention read lock null lock

The following table summarizes how locks interact. Short Lock Interactions write read/inten. write intention write update read intention read null read/ inten. write blocks blocks blocks blocks blocks blocks blocks inten. write blocks blocks inten. read blocks

write blocks blocks blocks blocks blocks blocks

update blocks blocks blocks blocks

read blocks blocks blocks

null

Short Locks and the First Instance
Implicit Write lock on class object when inserting first instance Normally, when you create or modify an instance of a class, VERSANT acquires an "Intention Write Lock" on the class object in order to prevent the class definition from being changed while you are creating or modifying an instance of that class. An Intention Write Lock allows multiple transactions to create or modify instances. Beginning with Release 6.0.0, the creation of the first instance of an empty class is treated as a special case.
83

VERSANT Database Fundamentals Manual

When inserting the first instance, VERSANT acquires the much stronger Write lock on the class object. This stronger lock will block all other transactions trying to insert instances. This change eliminate all possibilities of transaction inconsistencies when inserting the first instance of a class, but it creates the possibility of a deadlock or lock timeout should multiple transactions try to simultaneously insert instances on a previously empty class. You may need to be aware of this behavior if you are installing a new production database or working in a development environment, because this behavior may mean that you may need to add application code to handle a deadlock or lock timeout. Alternately, whenever you define a class, you might want to insert a dummy instance and commit the change to initialize the class. The dummy instance can later be deleted, after other instances have been created. This situation rarely occurs in production applications, because the case of an empty class is not common.

84

VERSANT Database Fundamentals Manual

Persistent Locks
Persistent Lock Description
Persistent locks span transactions and sessions and survive a system disruption. Persistent locks imply a short lock and have additional functionality. Persistent locks have the following elements: Lock mode Lock level Queuing Notification Short lock functionality. Whether your lock can be broken by another user. What happens if an object already has a blocking lock. Notification if certain events occur.

Each of the above persistent lock elements is explained in a following section. Because persistent locks imply a short lock, see also the section "Short Lock."

Persistent Lock Mode
Following are persistent lock mode options. Persistent write lock As with a short write lock, a persistent write lock guarantees that you are the sole user of an object. A checkout of an object with a write lock creates a copy of the locked object in your personal database and places a persistent write lock on the object in the group database. Other users cannot check out the same object. A write checkout does not change the identity of the object. When you check in a write locked object, the copy in the personal database replaces the source object.

85

VERSANT Database Fundamentals Manual

c c++

O_PL_WRITE O_PL_WRITE

Persistent read lock As with a short read lock, a persistent read lock guarantees that an object will not change. A checkout of an object with a read lock creates a copy of the object in the personal database and places a persistent read lock on the object in the group database. Other users can also check out an object that has a persistent read lock, but they cannot modify it. A read checkout does not change the identity of the object. When you check in a read locked object, the copy in the personal database is dropped, and the lock on the source object is released. c c++ O_PL_READ O_PL_READ

Persistent null lock As with a short null lock, a persistent snapshot lock provides no access guarantees and is really no lock at all. A checkout of an object with a null lock creates a copy in your personal database without regard to its current lock state and without placing a lock yourself. It is useful when you want just to view data in its current state without modifying it and do not want to wait for release of any lock placed by another user. A null lock checkout creates an unlocked copy of the object with a new object identifier. When you end the long transaction with which the checked out object is associated, the copy in the personal database is not dropped. Explicitly checking in an object checked out with a null lock is the same as migrating an object to a new database. If you request a null lock in association with a checkout, any requests for a hard or soft lock level or for a particular queuing option are ignored.

86

VERSANT Database Fundamentals Manual

c c++

O_PL_NOLOCK O_PL_SNAPSHOT O_PL_NOLOCK O_PL_SNAPSHOT

Persistent Lock Level
You can set a persistent lock level of hard or soft. Persistent hard lock A hard level means that your persistent lock cannot be broken by another application process. c c++ O_PL_HARD O_PL_HARD

Persistent soft lock A soft level means that your persistent lock can be broken by another application process. c c++ O_PL_SOFT O_PL_SOFT

When you try to commit a transaction involving an object with a broken lock, an error occurs.

Persistent Lock Queuing
If a persistent lock request cannot be granted immediately, you can specify queuing options that cause your application either to wait, place a lock reservation, or give up. Following are the queuing options. Persistent lock wait If the object is not available for locking, VERSANT will keep trying to obtain the lock until the request times out. If the object becomes available before the request times out, then the lock request will be granted. If the object is not available after the request times out, then the error message OM_LO_BE_INCOMPAT will be returned, which means that there is already an incompatible persistent lock on the object. 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. c c++ O_PL_WAIT O_PL_WAIT

Persistent lock reserve If the object is not available for locking, VERSANT will immediately return the error message
87

VERSANT Database Fundamentals Manual

OM_LO_BE_INCOMPAT, which means that there is already an incompatible persistent lock on the object,

and then place a lock reservation on the object.

Placing a lock reservation on an object means that a notification message O_PL_OBJ_READY will be sent when the object becomes available. Getting the O_PL_OBJ_READY message does not mean that you now have a lock: you must repeat your lock request and that request will be evaluated again in the context of any other locks that exist at the moment when the request is made. c c++ O_PL_RESERVE O_PL_RESERVE

Persistent lock give up If the object is not available for locking, VERSANT will immediately return the error message OM_LO_BE_INCOMPAT, which means that there is already an incompatible persistent lock on the object, and make no further attempts to acquire the lock. c c++ O_PL_NO_BLOCK O_PL_NO_BLOCK

Persistent Lock Event Notification
You can request notification if your persistent soft lock has been broken, if someone else is waiting for your persistent lock, or if your reserved object is now ready: Persistent lock broken Send notification when your soft lock is broken by another user. c O_PL_LOCK_BROKEN c++ O_PL_LOCK_BROKEN #LOCKBROKEN

st

Persistent lock pending Send notification when someone else is waiting for your lock. c O_PL_REQ_PENDING c++ O_PL_REQ_PENDING #REQPENDING

st

88

VERSANT Database Fundamentals Manual

Persistent lock object ready Send notification when an object is ready. c O_PL_OBJ_READY c++ O_PL_OBJ_READY #OBJREADY

st

Persistent lock event notification description The persistent lock event notification options can be combined with the logical OR operator. Event notifications are normally sent in the form of electronic mail, but you can customize event notification. For instructions on how to customize event notification, please call Versant Technical Support. Electronic mail notifications have the following general format:
Versant Event Notification: To: user@host From: user@host Event: event Object: object identifier in "dbname"

The From: field identifies the user who generated the event. The To: field identifies the user affected by the event. The system evaluates your outstanding message requests each time a short transaction ends with a commit or rollback. You can also monitor objects for object related events by using a separate "monitor object" statement. Monitoring an object tells you if another application process has versioned an object, read an object, or committed an update on an object previously checked out in write mode. The read option includes, but is not limited to, notification when an object is checked out in read mode. Monitor object You can also monitor objects for object related events by using a "monitor object" function or method. c o_monitorobj() c++ monitorobj() monitorOnEvents:

st

89

VERSANT Database Fundamentals Manual

C/VERSANT — Some functions require use of a an "intent" parameter. This parameter is reserved for future use.

Persistent Lock Precedence
Since setting a read or write lock mode in a persistent lock has the same effect as setting a read or write short lock, lock precedence and interaction rules apply to persistent read and write locks as if they were short read or write locks. Turning locking off for a database disables short locks but has no effect on persistent locks. This means that you can set persistent locks even if short locking has been turned off in a group and/or personal database. For example, if you have a persistent write lock on an object, even if short locking has been turned off in its database, other users will be blocked by the persistent write lock just as if you had set a short write lock.

Persistent Lock Request Handling
Because personal databases allow only a single user, you cannot set a persistent lock on an object in a personal database. Persistent locks are usually, but not always, used in conjunction with object checkouts. Persistent locks are always enabled, even if you have turned locking off in the server process profile for a database. Persistent locks are not set immediately upon request. Rather, they are granted in two steps: 1. Short lock attempt

The system immediately tries to set a short lock that matches the lock mode specified in your persistent lock request and then logs your request for a persistent lock. 2. Persistent lock attempt

At the next commit or checkpoint commit, the system tries to set your persistent lock. A short lock matching the lock mode specified in your persistent lock request is granted if all of the following conditions are true: • • • There are no incompatible short locks. Either there are no persistent locks with an incompatible lock mode, or all persistent locks with an incompatible lock mode have a soft lock level and you have requested a hard lock level. Either you have reserved the object with a persistent lock compatible with all active persistent locks, or there are only persistent lock reservations with lock modes incompatible with other active locks.

If you are not immediately granted a short lock matching your persistent lock mode parameter, what happens
90

VERSANT Database Fundamentals Manual

next depends upon other parameters you have supplied: • • If you have specified either "give up" or "place reservation if blocked" in the lock wait option of your persistent request, then the system gives up immediately. If you have specified "wait" in your lock wait option, the system keeps trying until the request is timed out.

If you are granted a short lock that matches your persistent lock mode parameter: • • • A subsequent short transaction rollback will drop both the persistent lock request and the matching short lock. A subsequent short transaction commit or checkpoint commit records the persistent lock in the database. A subsequent undosavepoint has no effect on either the short lock or the persistent lock request.

If at commit time the requested objects have still not been locked at a harder level by another user, then your entire persistent lock, including the level, wait, and event requests, is granted and logged. After your persistent lock request has been granted, your queuing options are irrelevant and what happens next depends on your lock level and your notification requests. What happens to your lock depends upon your level: Hard lock level If you have a hard lock, then your lock continues until you release it. Soft lock level If you have a soft lock, then your lock can be broken at any time by a request made by another application process for an incompatible hard lock. An error will be raised if you try to checkin an object with a broken lock or if you try to commit a long transaction with which a broken lock is associated. The notifications you will receive depend upon your notification options: Lock broken If you specified the "lock broken" option when you made the lock request, then you will be notified immediately if your lock is broken. An error will also be raised if you try to check in an object with a broken lock or if you try to commit a long transaction with which a broken lock is associated. Request pending If you specified the "request pending" option when you made the lock request, then you will be notified if another user is waiting for your lock.
91

VERSANT Database Fundamentals Manual

If your persistent lock request is not granted, your lock level options become irrelevant and what happens next depends on your queuing and notification requests. Whether you wait or not depends on your queuing options: Wait If you specified the "wait" option, VERSANT will keep trying to obtain the lock until the request times out. If the object is not available after the request times out, you will receive the error message OM_LO_BE_INCOMPAT. No wait option If you specified the "no wait" option, you will immediately receive the error message
OM_LO_BE_INCOMPAT.

If you request another persistent lock for the same object in the same short transaction, the system may or may not retry to gain the lock: • The system will retry if you request a lock level with higher precedence than you already have; for example, if you have a persistent read lock, the system retries if you request a persistent write lock. The system ignores a request for a lock with a lower precedence level than a lock that has already been granted. For example, if you have a write lock, a request for a read lock is ignored. A request to unlock a persistent lock, if last in a sequence of requests in a short transaction, is always granted at the next commit. However, an unlock request does not immediately release any existing short locks in case it is followed by a higher level request.

• •

For example, suppose you request the following persistent lock: Lock mode — read Lock level — hard Wait option — wait Upon receiving this request, the system immediately logs your request and then tries to get a short read lock. • If a short read lock exists:

You immediately get a short read lock. If nothing else changes, at the next commit, you get your persistent read lock. • If a short write lock exists:

Then you are blocked, but the system keeps trying until timed out. If timed out, you receive a "lock
92

VERSANT Database Fundamentals Manual

timeout" error. • If a persistent read lock exists:

You immediately get a short read lock. If nothing else changes, at the next commit, you get your persistent read lock. • If a persistent hard write lock exists:

You are blocked, and the system keep trying until timed out. • If a persistent soft write lock exists:

You immediately get a short read lock. If nothing else changes, at the next commit, you get your read persistent lock. As soon as the other user performs a checkin or long transaction commit, that user receives an error message.

Persistent Lock Actions
Set persistent lock c o_acquireplock() o_gcheckout() o_pathpcheckout() o_pcheckout() acquireplock() gcheckout() pcheckout()

c++

set persistent lock check out object check out object check out object set persistent lock check out object check out object

Persistent locks are not set until a commit or checkpoint commit occurs. Release persistent lock c o_checkin() o_checkinreturnobjs() o_endsession() o_releaseplock() checkin() endsession() releaseplock()

c++

check in objects check in objects end session release persistent lock check in objects end session release persistent lock

After a request to release a persistent lock, the persistent lock is released at the next commit or checkpoint commit.

93

VERSANT Database Fundamentals Manual

Persistent Lock Description

C/VERSANT — Persistent locks are described in the o_lockdesc data type. C++/VERSANT — Persistent locks are described in an instance of VLockDesc.

94

VERSANT Database Fundamentals Manual

Chapter 6: General Programming Notes
This chapter contains general programming rules and usage notes relevant to all interfaces. Please refer to the respective language (C/C++/JVI) reference manuals for further details. Name Rules...................................................................................................................................96 Session Firewall .............................................................................................................................99 Database Connection Rule ............................................................................................................ 100 Schema Evolution ........................................................................................................................ 101 Overview ................................................................................................................................ 101 Adding a Class ......................................................................................................................... 101 Deleting a Class ....................................................................................................................... 101 Renaming a Class ..................................................................................................................... 102 Changing an Inheritance Tree .................................................................................................... 102 Adding, Deleting or Renaming an Attribute ................................................................................. 103 Changing an Attribute's Data Type ............................................................................................. 103 Propagating Schema Changes.................................................................................................... 104 Verifying Schema ..................................................................................................................... 105 Mixing Releases........................................................................................................................... 106 Application Failure ....................................................................................................................... 107 Error Messages that are Incomplete................................................................................................ 108

95

VERSANT Database Fundamentals Manual

Name Rules
Name length Maximum name lengths and default values imposed by VERSANT are: Name Site User Database .h specification file .cxx implementation Class Attribute Method Session Short transaction Long transaction Name characters VERSANT does not allow spaces in names, including login and database names. Name of remote database Specify a remote database with dbname@site syntax. Name of a class Class names should be unique to their database. When objects are checked out or migrated, class names cannot conflict with existing class names in the target database. Name of an attribute Attribute names should be unique to their class and superclasses.
96

Maximum number of characters 223, should be null terminated 31 31, should be null terminated per your operating system and compiler per your operating system and compiler 16,268, should be null terminated, also limited by compiler 16,268, should be null terminated, also limited by compiler 16,268, should be null terminated, also limited by compiler 31, should be null terminated, default is user name 31, default is user name 31 less username less 1, default is user name (VERSANT internally appends !username to any name you specify)

VERSANT Database Fundamentals Manual

Specifying a name with a variable

C/VERSANT and C++/VERSANT — When using a variable to supply a name, you must first allocate memory for the variable with malloc() or the equivalent for your operating system. Remember to add one character for the null terminator.
For example: newAttrName = malloc(sizeof("ANewNameOfAnyLength")+1); o_err o_renameattr(...

Names returned to a vstr

C/VERSANT and C++/VERSANT — Several methods and functions, such as o_classnameof(), return names to a vstr. When you are finished using the names returned in the vstr, remember to deallocate the vstr memory using a routine such as o_deletevstr().
Name for null database

C++/VERSANT — In every C++/VERSANT method except beginsession(), whenever you see a database name argument, you can specify NULL to use the default database. Before a session starts, there is no default database, so you should specify a database when you begin a session with beginsession().
When you begin a session with the PDOM beginsession() method, the database specified becomes the session workspace and the default database. You can later change the default database by using the PDOM::set_default_db() method. Changing the default database does not change which database is being used as a session workspace. It does change the database in which objects are created, since creating a new, persistent object with O_NEW_PERSISTENT() creates that object in the current default database. Logical object identifiers for new objects are generated from the session database, even if it is not the default database. Name of nested collection

C++/VERSANT — C++/VERSANT allows you to nest Collection classes to any depth. For example, you can create a dictionary whose values are a list:
VEIDictionary

Name of attribute in query and index methods

C++/VERSANT — Methods which query or index on an attribute need a precise database attribute name even when referring to a private attribute. This precise name qualifies the attribute name with the class name, as in Employee::age. The query and index methods that need a precise name are select(),
97

VERSANT Database Fundamentals Manual

pcheckout(), createindex(), and deleteindex().

Precise attribute names are needed by these methods, because a derived class could conceivably inherit attributes with the same name from numerous superclasses along one or more inheritance paths. Even if there is no initial ambiguity, classes may later be created which do cause ambiguity.

98

VERSANT Database Fundamentals Manual

Session Firewall
You must start a session before using VERSANT functions, methods, and persistent objects. The only exceptions are functions and methods that set session parameters.

99

VERSANT Database Fundamentals Manual

Database Connection Rule
You must explicitly connect with a database before accessing it. To connect with the session database, use a "begin session" function or method. After beginning a session, to connect with other databases, use a "connect database" function or method. Connecting to a database does not change the default database. To change the default database, use a "set default database" function or method.

100

VERSANT Database Fundamentals Manual

Schema Evolution
Overview
For each class of object that is stored in a VERSANT database, the class definition is also stored. This stored definition (schema) must be identical to the class definition in your program files to avoid unpredictable results. In addition, when you change a class definition, existing instances of the changed class must adapt to the new definition. This section tells how to update stored class and instance objects with evolving class definitions. Most kinds of schema changes do not require explicit conversion of instances. Each time your applications access an object, VERSANT automatically adjusts the object's structure to the current class definition as needed. This "lazy updating" feature spreads the cost of instance conversions over time, and avoids the need to shut out applications while global conversions are performed. The exceptional schema changes that require global conversions are noted below. Lazy updating does not alter object identifiers, so references to affected objects remain valid after the conversion. For this reason, lazy updating is preferable to manual conversion involving the creation of new objects. Each programming language requires different mechanisms for communicating schema changes to a VERSANT database. The following summarizes the basic mechanisms and provides an overview of the language-specific variants. For more language-specific detail, please see the reference manual for your language interface.

Adding a Class
Adding a new class has no impact on existing objects in the database, so no special precautions are necessary. The new class is defined in the usual language-specific way. The class name must be unique within the relevant databases. If the new class is intended to become a superclass of any existing class, and must therefore be inserted into an inheritance chain, each intended subclass must be redefined and its instances must be converted. For details, see "Changing an Inheritance Tree" below. c c++ o_defineclass()

Use schcomp utility to generate .sch file from .imp file

Deleting a Class
Deleting a class requires a language-specific drop-class method or function, shown below. All instances of the
101

VERSANT Database Fundamentals Manual

target class are deleted from the database, as well as subclasses and their instances. With the C++/VERSANT interface, deleting a class also deletes any class with an attribute containing a link to the class being dropped. For example, if class B has an attribute Link that references an instance of A, then dropping A also drops B. This prevents dangling references. c c++ util o_dropclass() dropclass() dropclass

Renaming a Class
With the C or C++ interfaces, however, renaming a class invalidates instances in a way that cannot be accommodated via lazy updating, as most other schema changes can. Therefore, a multi-step conversion is required: 1. 2. 3. 4. Add a new class that has the desired class name. Create and run a program to create instances of the new class based on the instances of the old class. Repair any references to the old instances. Delete the old class, and with it the old instances.

For example, suppose you want to rename the Book class so its name is Publication: 1. 2. 3. 4. Add a new Publication class, based on the Book class definition. Create and run a program to create instances of Publication based on instances of Book. For each reference to a book, substitute a reference to the equivalent publication. Delete the Book class, and with it, all instances of Book.

Changing an Inheritance Tree
With the C or C++/VERSANT interfaces, however, changing a class's inheritance chain invalidates instances in a way that cannot be accommodated via lazy updating, as most other schema changes can. Therefore, a multi-step conversion is required: 1. 2. 3. 4.
102

Rename the class whose inheritance chain is being altered (see "Renaming a Class" above). Add a new class that has the original class name and the new inheritance chain. Create and run a program to create instances of the new class based on the instances of the old class. Repair any references to the old instances.

VERSANT Database Fundamentals Manual

5.

Delete the old class, and with it the old instances.

For example, suppose a hypothetical Book class currently inherits from Object. You want it to inherit from a newly created Product class, resulting in the following inheritance chain:
Object Product Book

The steps for accomplishing this conversion would be: 1. 2. 3. 4. 5. Rename Book to OldBook. Add a new Book class that has Product as its superclass. (Product attributes, such as price, might also need to be removed from Book's definition.) Create and run a program to create instances of Book based on instances of OldBook. For each reference to an OldBook, substitute a reference to an equivalent Book. Delete the OldBook class, and with it all instances of OldBook.

Adding, Deleting or Renaming an Attribute
You can add, delete or rename an attribute in a single step; VERSANT updates instances automatically as they are accessed, initializing a new attribute's value to zero or NULL. If you modify the attributes in a superclass, subclass instances are also updated automatically. Data in a renamed attribute is not affected. Data in other attributes also is not affected. With the C++/VERSANT interface, adding or dropping an embedded class or struct requires manual conversion of the class and its instances. c c++ o_newattr(), o_dropattr(), o_renameattr() Modify schema files, then use sch2db to update database. Use synclass() to synchronize other databases.

Changing an Attribute's Data Type
Changing an attribute's data type requires multiple steps, but the steps differ depending on whether you are using a typed or untyped programming language. In C or C++, the steps are: 1. 2. Rename the attribute. Add a new attribute with the new data type.

103

VERSANT Database Fundamentals Manual

3. 4.

Create and run a program that casts each old-attribute value to the new data type, and then stores the resulting value in the new attribute. Delete the old attribute.

For example, to change the data type of Book's price attribute from int to float: 1. 2. 3. 4. Rename the price attribute to oldprice. Add a new attribute named price, with float as its data type. Create and run a program that casts each book's oldprice integer as a float, and stores the result in the price attribute. Delete the oldprice attribute.

When the data type is inferred, no special action is required: VERSANT accommodates values of any recognized data type automatically. If the database contains old instances, however, this results in a mix of old and new data types for the attribute, which may cause problems for your applications. In that case, you would need to create an informal program to fetch each old object, recast the target attribute's value to the new data type, and then update the object in the database.

Propagating Schema Changes
Communicating a schema change to one or more VERSANT databases depends on the programming language. Class changes that are propagated in this way do not affect object identifiers, so references to the affected objects within an application remain valid even after the class is changed. The few exceptions to this rule are noted in the discussions of specific kinds of changes above. Instances of a changed class, or of its subclasses, are aligned with the new class definition only as they are accessed. This lazy updating mechanism spreads the cost of schema evolution over time, and avoids the need to perform a global sweep that would shut out normal database usage. No special action is required when migrating or checking in objects. If an object is moved to a database in which its class has not been loaded, VERSANT automatically migrates the class object as well as the instance. If the class is already defined in both the source and target databases, an error is generated unless the two class definitions are identical. C Because the C language does not support class definitions, the C/VERSANT interface requires that you create a C program to implement each set of schema changes. The C/VERSANT interface provides a
104

VERSANT Database Fundamentals Manual

specific method for implementing each type of schema change, such as o_dropclass() or o_renameattr(). C++ In the C++/VERSANT interface, the Schema Change Utility (sch2db) is used to propagate changes in schema (.sch) files to a database. To reload a class definition in multiple databases, you can run the Schema Change Utility separately on each database, or run it on one database and then reconcile differences in other databases with the synclass() method. For details about the Schema Change Utility and the synclass() method, see the C++/VERSANT Reference Manual.

Verifying Schema
At any given moment, the schema as known to the database may or may not be identical to the schema as known to your application code, depending on how recently and how rigorously you and other developers on your team have synchronized these two views of the schema. Because of this potential for mismatch, especially on large, multi-developer projects, it's a good idea to confirm the schema before testing or deploying your applications. Each of the VERSANT interfaces for class-based languages, such as C++ provides a facility for confirming the schema. In each case, the nature of the facility is tailored to the development environment. C++/VERSANT The Schema Change Utility (sch2db), which is normally used to change class definitions in a VERSANT database so they match the definitions in schema files, can also be used to report mismatches without making any changes. This reporting feature is enabled with the -n flag on the command line that is used to invoke sch2db.

105

VERSANT Database Fundamentals Manual

Mixing Releases
Compatibility of Releases The following describes the compatibility of this release with previous releases. Most objects can be shared C++ objects may be shared among applications created with Visual C++, and C Set++ compilers and with xlC compiler independent releases. Release 5 databases can be converted to Release 6 databases using convertdb utility. To invoke convertdb: convertdb databasename

You must end all long transactions and then stop the database with stopdb before and after running convertdb. Some Release 5 applications can use Release 6 databases Applications linked with the VERSANT Release 5 two process system library, liboscfe.a, can access, create, update, and delete objects in VERSANT Release 6 databases if you create a new .oscxxyyzz file. On the machine containing the Release 6 database, the installation process will have created a file
/etc/.osc06yyzz, where yy is your minor release number and zz is your maintenance release number.

The purpose of this file is to tell VERSANT at runtime the location of its software root directory. On the machine containing the 6.yy.zz database:

• •

To access with VERSANT 5.0.8 copy .osc06yyzz to .osc050008. To access with VERSANT 5.2.2 copy .osc06yyzz to .osc050202.

After making this change, your applications compiled with previous releases will only be able to access 6.yy.zz databases on the target machine, although they can continue to access databases created with previous releases that exist on other machines. Applications created with previous releases and linked with the VERSANT one process system library, libosc.a, cannot access VERSANT 6.0.0 databases.

106

VERSANT Database Fundamentals Manual

Application Failure
If an application terminates abnormally and you are running with logging turned OFF, you will probably have to reset the database. This is because with recovery features turned off, VERSANT will not be given an opportunity to restore the database to a consistent state. To reset the database: 1. 2. Run the stopdb utility. Restart the database with startdb.

If logging and recovery are turned ON, then the next time you try to use the database, VERSANT will automatically rollback all incomplete transactions that may be corrupting the database and restore conditions to a consistent state. VERSANT uses shared memory and semaphores for its inter-process communications. If an application does not finish normally, shared memory resources may not be released. To release shared memory resources after a failed application: 1. 2. 3. 4. Run the stopdb utility. If stopdb fails for some reason, manually remove shared memory, if any, by using the UNIX ipcrm command. Restart the database with startdb. If step 1 does not succeed, you will have to forcibly stop the database. For information on how to forcibly stop a database, call Versant Customer Support.

You can use the UNIX ipcs command to verify that all shared memory and semaphores have been released.

107

VERSANT Database Fundamentals Manual

Error Messages that are Incomplete
If error numbers are displayed without an accompanying error message, then either your VERSANT installation is incomplete or needed environment variables have not been set correctly. See the "Installation" chapter in your Release Notes.

108

VERSANT Database Fundamentals Manual

Chapter 7: Object Movement
Object Movement Overview ......................................................................................................... 110 Object Migration.......................................................................................................................... 111 Object Migration Usage Notes ................................................................................................... 111 Object Migration Actions........................................................................................................... 112 Object Checkout.......................................................................................................................... 113 Object Checkout Overview........................................................................................................ 113 Object Checkout Actions........................................................................................................... 113 Checkouts, Locks, and Versions ................................................................................................. 114 Checkouts, Locks, and Links ...................................................................................................... 116 Checkout General Notes ........................................................................................................... 117 Object Checkin............................................................................................................................ 118 Object Checkin Overview.......................................................................................................... 118 Object Checkin Actions............................................................................................................. 118 Checkins, Locks, and Versions ................................................................................................... 119 Object Checkin General Usage Notes ......................................................................................... 120

109

VERSANT Database Fundamentals Manual

Object Movement Overview
VERSANT allows you to move objects from one database to another with the following mechanisms: Object migration Migrating an object moves it permanently from one database to another. Object checkout A checkout creates an object in a personal database that is a copy of an object in a group datatabase. Object checkin A checkin moves a new or previously checked out object from a personal database to a group database.

110

VERSANT Database Fundamentals Manual

Object Migration
Object Migration Usage Notes
Migrating an object moves it permanently from one database to another. Migrating an object is useful when you want to distribute data to take advantage of available hardware, reduce network traffic by placing data near users, and/or move data from a development environment to a production environment. Object identity When you migrate an object, the object identifier of the object is not changed. This means that you do not have to change code that references an object or update other objects that have links to the migrated object even though the object has been moved to a new location. Locks Migration routines acquire a write lock if the object does not already have one. This ensures that you are the sole user of the object when you migrate it. Schema When you migrate an object, copies of class and superclass objects are made in the target database. If a class or superclass exists with the same name in the target database but with a different definition, an error will be returned. To resolve differences in schema definitions, you can use the "synchronize" method or other interface specific mechanisms. Checked-out Checked-out objects You cannot migrate a checked-out object. An attempt to migrate a checked-out object will cause an error. To migrate a checked-out object, you must first return it to its source database and then move it from there. Versioned objects You cannot migrate a versioned object. An attempt to migrate a versioned object will cause an error. Checkin routines You cannot use a checkin routine to migrate an object from a group database to another database. You
111

VERSANT Database Fundamentals Manual

can use a checkin to explicitly return a checked out object to its source database. Commits A migration is not persistent until committed. If multiple objects are migrated in a transaction, either all the objects will be migrated if the transaction commits successfully or all objects will be returned to their original databases. Links to objects in personal databases When you check in or migrate objects created in a personal database to a group database, make sure that the checked in or migrated objects do not reference objects left in a personal database.

Object Migration Actions
Migrate object c c++ o_migrateobj() o_migrateobjs() migrateobj() migrateobjs()

Check in object A checkin can migrate a new object from a personal database to a group database. c c++ o_checkin() checkin()

112

VERSANT Database Fundamentals Manual

Object Checkout
Object Checkout Overview
A checkout creates an object in a personal database that is a copy of an object in a group datatabase. Checkouts are useful when you want to work on particular objects for a long period of time with a minimum of network traffic and while optionally being disconnected from other databases. Also, because the original objects remain in their source databases, you can safely elect to turn off transaction management and recovery in your personal database and thus bypass locking and logging overhead. The net result can be a significant improvement in performance. In a sense, a checkout causes a personal database to become an extension of a group database. When you check out an object, VERSANT will automatically associate it with the current long transaction. Later, you can return all objects associated with that long transaction simply by ending the long transaction. A checkout of a non-versioned object with a persistent read or write lock copies it from a group to a personal database. The copy object has the same logical object identifier as the source object. A checkout of a non-versioned object with a null lock creates a new object in a personal database that is a copy of the source object. The new object a logical object identifier that is different from that of the source object. A checkout of a versioned object creates a new version of the object in a personal database. The new object gets a logical object identifier that is different from that of the source object.

Group checkout of objects — Group checkouts allow you to replicate frequently used objects in multiple group databases. For information on group checkouts, please call Versant Technical Support.

Object Checkout Actions
You can check out objects either specifically or with a query. Checkout specified objects A group checkout copies specified objects to a personal database and optionally copies linked objects to a given number of link levels. In a group checkout, specified and linked objects can come from any number of different databases. The group checkout method will first search a specified database and then continue to search all connected databases, stopping as soon as all desired objects have been found.
113

VERSANT Database Fundamentals Manual

Even though you can use group checkout objects from multiple databases, performance is much better if all of the objects in a particular group checkout belong to the same database. Thus, to improve performance, you might want to make a separate group checkout for each database from which you want objects. c c++ o_gcheckout() gcheckout()

Checkout found objects A predicate checkout copies objects that satisfy a search predicate to a personal database. You cannot use a predicate checkout also to checkout linked objects, but you can specify whether you want instances of subclasses also to be evaluated and checked out. If you need to check out linked objects, you can use a multi-level select query to identify the objects that you want to checkout and then check them out with a group checkout. Find and check out objects of a class c c++ o_pathpcheckout() o_pcheckout() pcheckout()

Checkouts, Locks, and Versions
What happens when you check out an object depends upon your lock request and whether the object is versioned or non-versioned. Checkout non-versioned objects non-versioned When you check out an object, you can place a persistent read, write, or null lock on the original object in the group database. Persistent write or read lock — A checkout of a non-versioned object with a persistent read or write lock copies it from a group database to the personal database used as a session database. Also, the requested persistent lock is set on the source object in its source database. The copy of the source object that is created in your personal database will have the same object identifier as the original. After the checkout, your queries will see the object in your personal database and not in the source database, but queries made by others will see the object in the source database. After the checkout, you can upgrade or release a persistent lock on the copy in your personal database. If you upgrade the lock, the upgrade will occur on the source object. If you release the lock, the checkout of that object will be rolled back. For a lock upgrade or release request to succeed, you must be connected to the source group database at the time of the request. A checked out, non-versioned object with a persistent read or write lock becomes associated with the current long transaction. This means that later you can check in all such objects to their source databases
114

VERSANT Database Fundamentals Manual

simply by ending the long transaction. If you attempt to delete a non-versioned object which has been checked out in write or read mode, an error will occur. To delete the object, you must check it in and then delete it from its source database. If an object has been previously checked out with a persistent read or write soft lock, you can override the soft lock with a hard lock and then check out the object. To break the soft lock, you must first use an explicit "set persistent lock" routine to acquire the necessary hard lock. This routine will fail if there is a conflicting persistent hard lock on the object, as hard locks are not breakable. A persistent write-hard lock will break a persistent read-soft lock or a write-soft lock, and a read-hard lock will break a write-soft lock. A read-hard lock will not break a read-soft lock, because there is no contention. Persistent null lock — A checkout of a non-versioned object with a null lock creates a new object in a personal database that is a copy of the source object. By definition, no persistent lock will be set on the source object. The new object will have a new object identifier and have no connection to the original object. This means that a query based upon search conditions will see two similar objects, one in your personal database and one in the source database, and that ending a long transaction will not perform a checkin of the copy object. Checkout versioned objects A checkout of a versioned object always creates a new version of the object in a personal database. A persistent lock will not be set on the source object, even if requested, because the checked out object is new and exists only in the personal database. To use versioning behavior with checkouts, you must convert an object to a versioned object with the prepare to version routine before checking it out. If you invoke a prepare to version routine on a checked out object, an error will be returned. Checkout all objects For both non-versioned and versioned objects, existing locks are tested against the lock requested by the checkout. If there is a blocking lock, the checkout will not occur. If there is no blocking lock, the checkout will occur. You can check out a mixture of versioned and non-versioned objects. The behavior that occurs will automatically differ depending upon the type of object involved. Turning locking off for a database disables short locks but has no effect on persistent locks. This means that a checkout can set persistent locks even if short locking has been turned off in a group and/or personal database. For example, if you have a persistent write lock on an object, even if short locking has been turned off in its database, other users will be blocked by the persistent write lock just as if you had set a short write lock.
115

VERSANT Database Fundamentals Manual

Since the purpose of group databases is to allow access to objects by multiple users, it is rarely safe to turn short locking off in a group database. However, for performance reasons you may want to turn short locking off in a personal database if you are accessing the objects with only a single application process. If you are accessing objects in your personal database with multiple processes, then you should normally leave short locking on.

Checkouts, Locks, and Links
What happens when you check out an object depends upon whether you also checkout linked objects, whether the object is versioned or non-versioned, and what kind of lock you request. Behavior may also depend upon whether you check out objects and linked objects in one operation or in separate operations. Checkout non-versioned objects with read and write locks non-versioned If you check out a non-versioned object with a read or write lock but do not check out its linked objects, the links from the checked out object to the linked objects will continue to point to the target objects in their source databases. This means, that accessing a linked object will require a remote access and a remote database connection. If you check out both a non-versioned object and its linked non-versioned objects in read or write mode, links will point to the target objects in their new locations in the personal database, because links are based upon object identifiers and checking out objects in read or write mode does not change identifiers. This means that accessing a checked out linked object will not require a remote access or remote database connection. This behavior for read and write mode checkouts occurs regardless of when the checkouts occur, whether in one operation or in separate checkouts of objects and their linked objects. A link always points to the current location of an object. non-versioned Checkout versioned objects and non-versioned objects with null locks Since null lock and versioned object checkouts create new objects, links are handled somewhat differently than in read and write mode checkouts. If you check out an object with a null lock or a versioned object but do not check out its linked objects, the links in the new object will continue to point to the target objects in their source databases. If you check out a null locked or versioned object and also checkout its linked objects in a single group checkout, the links in the new objects will be adjusted to point to the new linked objects created in the personal database. If you check out a null locked or versioned object and later checkout its linked objects in a separate operation, the links in the new object will point to the original objects in their source databases.

116

VERSANT Database Fundamentals Manual

Checkout General Notes
Checkout and long transaction A long transaction tracks checked out objects using long transaction objects in the databases that are the sources of the checked out objects. Each time an object is checked out, a long transaction object in its database is updated. Long transaction objects are maintained even if logging has been turned off in a database. However, logging must be turned on to roll back a checkout or checkin. Checkout and schema evolution For each object, a checkout will also copy its class object and the class objects for superclasses, linked objects, and embedded objects if they do not already exist in the personal database. These class definitions are needed so that you can access the checked out object, create new objects of the same class, create new subclasses, and use embedded classes normally. If a class already defined in the personal database has the same name but a different definition, the checkout will return an error, and you must stop and synchronize the definitions in order to make the checkout. When a non-versioned object is checked out with a read or write lock, VERSANT will prevent changes from being made to class and superclass objects during the period of the checkout. Although VERSANT will allow you to change the class objects in the personal database, you must resolve any differences in class definitions before you can make a checkin. This means that you cannot use checkout/checkin mechanisms to change schema, even if you explicitly checkout a class object. There are numerous ways to evolve schema in different databases in a consistent manner. One way is to change a class definition in one database and then use an interface specific "synchronize class" routine or utility to change it in another. Another way is to change class definitions separately in all databases involved. Checkout and transaction commit A checkout is not persistent until committed. This means that a checkout is atomic: either all objects involved in a checkout are checked out when the transaction commits or none are.

117

VERSANT Database Fundamentals Manual

Object Checkin
Object Checkin Overview
A checkin moves a new or previously checked out object from a personal database to a group database. A checkin is useful if you have been working on objects in a personal database while being disconnected from other databases and now want to update other databases with your results. Checking in a new non-versioned object migrates it from a personal database to a group database and drops the original object in the personal database. Checking in a non-versioned object previously checked out with a read or write lock returns it to its source database and drops the copy in the personal database. Checking in a non-versioned object previously checked out with a null lock migrates it from a personal database to a group database and drops the object in the personal database. Checking in a versioned object creates a new, child version of the object in a group database and leaves the parent object in the personal database.

Object Checkin Actions
You can check in objects by ending a long transaction or by using an explicit checkin routine. Check in objects by ending a long transaction When you end a long transaction, you can commit, rollback, or continue the current long transaction. Committing a long transaction checks in all objects that have been checked out in the current long transaction and releases all locks held on the checked out objects. Rolling back a long transaction drops the checked out objects from the personal database and releases all locks held on the checked out objects. Continuing a long transaction leaves the checked out objects in the personal database and maintains persistent locks from one session to another. c c++ o_endsession() endsession()

Check in specified objects An explicit checkin will check in specified objects. These objects can either be new objects that you want
118

VERSANT Database Fundamentals Manual

to migrate to the group database or objects that have been previously checked out. An explicit checkin allows you either to hold locks on previously checked out objects or to set locks on new objects being checked in. A checkin always returns a checked out object to its source database even if you specify a different database in the checkin routine. c c++ o_checkin() o_checkinreturnobjs() checkin()

Checkins, Locks, and Versions
Checkin behavior depends upon locks previously set and differs for versioned and non-versioned objects. If you check in a mixture of versioned and non-versioned objects at one time, what happens will depend upon the type of object involved. non-versioned Checkin non-versioned objects Checkins of non-versioned objects do not change object identity, although what happens differs depending upon whether the object is a new object or an object previously checked out with a persistent write or read lock. Write lock — If a non-versioned object has been checked out with a write lock, a checkin will replace the original object in the source database with the checked out object and delete the copy in the personal database. Read lock — If an object has been checked out with a read lock, a checkin will not change the original object in the group database but will drop the copy in the personal database. New object or null lock — If an object has been checked out with a null lock or was created in a personal database, ending a long transaction will have no effect on it, but you can use either an explicit "check in" or a "migrate object" routine to migrate it from the personal database to a group database. Broken lock — If you checked out an object with a persistent read or write lock with a soft level and if the soft lock has been broken by another user requesting a hard lock, you will not be able to checkin or migrate that object. Checkin versioned objects If a versioned object has been checked out, ending its long transaction will have no effect on that version, because checking it out created an entirely new version in the personal database with only a child-parent relationship with the source object in the group database. If you use an explicit "check in" routine on a previously checked out versioned object, a new version of
119

VERSANT Database Fundamentals Manual

that object will be created in the group database. VERSANT will traverse the version graph to find the original parent object in the group database and, by default, use it for the checked-in version. However, you can specify a new parent as a parameter in the checkInTo: message. The checkin will not delete the versioned object in the personal database. After a checkout of a versioned object, the original parent object may be deleted in the source group database. If the parent has been deleted, a checkin of a versioned object will create a new version derivation graph with the checked in object as the root of this graph. Deleting a versioned object from a personal database has no effect on the version derivation graph in the group database.

Object Checkin General Usage Notes
Checkin and schema evolution You cannot use checkins to change class definitions. If you try to checkin an object whose class name is the same as a class that exists in the target database but whose definition is different, an error will be raised. You will then have to resolve the differences in definitions. Checkin and class objects After a checkin, class and superclass objects for both checked out and new objects remain in the personal database even if all of their instances have been checked in or migrated. Checkin and source database Checkins always return checked out objects to their source database even if you specify a different database in an explicit "check in" routine. Checkin object deletion You cannot use a checkin to delete an object. If you check an object out in read or write mode, an attempt to delete it will cause an error. If you handle the error and continue, the next checkin caused by ending the long transaction will restore the original object in its source database and release its persistent lock. Checkin and transaction commit A checkin is not persistent until committed. If you rollback a checkin or if the system crashes before a checkin is committed, then the checkin will have no database effect. In other words, a checkin is atomic: either all objects involved in a checkin are checked in when the transaction ends or none are.

120

VERSANT Database Fundamentals Manual

Chapter 8: Object Versioning and Configuration Management
Object versioning is a VERSANT feature that allows you to track the evolution of object states. Configuration management is a low-level framework upon which you can build a configuration management system. It uses a "smart object" architecture for connecting objects logically to create different versions of the same data. Object Versioning ........................................................................................................................ 122 Overview ................................................................................................................................ 122 Versioning Actions ................................................................................................................... 123 Versioning Example .................................................................................................................. 129 Configuration Management........................................................................................................... 132 Overview ................................................................................................................................ 132 Architecture ............................................................................................................................ 133 Usage ..................................................................................................................................... 138 Example Demo Program............................................................................................................ 145

121

VERSANT Database Fundamentals Manual

Object Versioning
Overview
Versioning purpose One of the purposes of versioning is to allow the tracking of the evolution of object states. An object or a group of objects can have any number of versions whose interrelationships are automatically logged. Another purpose of versioning is to make a particular object always available for checkout to a personal database regardless of the locks that have been set on it. Constant availability is consistent with locking, because checking in a versioned object always creates a new version of that object. Version Derivation Graph VERSANT tracks the version derivation history of objects across databases in a database system, even when objects are checked out, by using a version derivation graph. The first version of an object becomes the root of the object's version derivation graph. The derivation graph branches when sibling versions are created and merges when a single version is created from multiple parent versions. Each node of the derivation graph references all predecessors and successors, points to the versioned object itself, and contains some descriptive information about the versioned object, such as creation time and creator identification. The coordination of version derivation across database boundaries is achieved through the concept of a "virtual" version derivation graph, which is an extension of a version derivation graph for a single database. In a virtual version graph, related versions in different databases are connected through virtual links automatically created by checkout and checkin operations. These virtual links are then used by the Version Manager module of the VERSANT Manager to find a proper parent for a version during subsequent checkouts and checkins. Automatic maintenance of the version graph means that you do not have to keep track of derivation histories across databases, which is important since you may not know what other applications are doing. You can override the default handling of version derivations by explicitly naming a parent version in a target database. If you do specify a parent during a checkin, the Version Manager records the new derivation link and does not traverse the derivation hierarchy. VERSANT can resolve version relationships at runtime with dynamic binding to a generic instance. One of the versions is a default version, and the current default is recorded in the generic instance. Initially the default
122

VERSANT Database Fundamentals Manual

version is the most recent version in the derivation graph. However, you can set the default. The default version is recorded in a "generic instance" associated with the versioned object. There is only one generic object instance for a versioned object. At runtime you can use the generic instance to find the version that has most recently been specified as the default version. An application program can also statically bind to a specific version. When the last version in a version tree for a database is deleted, the generic version is also deleted, even if some versions have been checked out. When you perform a query on a versionable class, all versioned object that meet the selection criteria are returned.

Versioning Actions
Create versioned object Is versioned object Any object can be explicitly or implicitly changed from a normal object to a "versioned" object, and you can ask any object whether or not it is a versioned object. Once an object is versioned, it is automatically handled differently from a non-versioned object. Each version of an object has a unique object identifier, a version status, and can have parent, child, and/or sibling relationships to other versions. You can also create a versioned object implicitly by creating a child version of it with a "create version" routine. Versioned objects are persistent objects in the full sense. When you query the database by selection, in addition to any non-versioned objects, any versioned objects that meet the search predicate are returned. You can then use various routines to determine if an object is versioned and what its version status is. Likewise, when you create a database index, it will index all objects of a class, including any versioned objects. Versioned objects cannot be migrated. A versioned object is always associated with the database in which it was first created.

123

VERSANT Database Fundamentals Manual

Create versioned object c c++ o_preptoversion() preptoversion()

Is versioned object c c++ o_isvsninst() isvsninst()

Create version Create version with checkout Create version with checkin After an object is versioned, additional versions can be created either explicitly with a "create version" routine, or automatically via checkout and checkin procedures. Each version is given a version number, assigned a status, and its parents and children are stored in a version graph. VERSANT stores each complete version, regardless of how similar it may be to its predecessors. When you create the first version of an object, the original object becomes the root of the object's version tree, and a generic object instance is created. If you try to create a version of a non-versioned object, the object will automatically be changed to a versioned object before the new version is created. You cannot version a checked out non-versioned object. After a non-versioned object has been checked out and you want to make a version of it, you must check it in, make it a versioned object, and optionally check it out again.

124

VERSANT Database Fundamentals Manual

Create version c c++ o_createvsn() createvsn()

Create version with check out of a versioned object c o_gcheckout() o_pathpcheckout() o_pcheckout() gcheckout()

c++

Create version with check in of a versioned object c o_checkin() o_checkinreturnobjs() o_endsession() checkin() endsession()

c++

Get version children Get version parents Add version parent A new version of an object is called a "child," while the original object is called a "parent." Versions that share the same parent are called "siblings." Each new version of an object has a child relationship to its source object. Once an object has been versioned, further versions can be explicitly created or implicitly created by use of checkouts and checkins. You can find all children or parents of any versioned object or the generic instance. You can explicitly add a parent version to an object. This is useful, say, if you have merged two parent objects and want to designate the new parent version as a parent of a particular child.

125

VERSANT Database Fundamentals Manual

Get version children c c++ o_getchildvsns() getchildvsns()

Get version parents c c++ o_getparentvsns() getparentvsns()

Add version parent c c++ o_addparentvsn() addparentvsn()

Get version status Set version status Versions have status levels assigned to them to provide update constraints. You can use routines to set and get their status. Transient version — A transient version is treated as an ordinary object and it can be updated or deleted. When a transient version is deleted its description is also deleted from the version derivation graph. Accordingly, a transient version can only occur as a leaf on a version graph, and you cannot downgrade a non-leaf version to a transient version. Working version — When a version becomes stable, it can be promoted to a working version, which is frozen and cannot be updated. A working version can be deleted to recover space, although its derivation history persists in a version graph because there may still be versions derived from it. Released version — A version can be upgraded to released status which means that it cannot be updated or deleted. You can downgrade or demote a version's status. For example, if you want to delete a released version, downgrade it to a working version and then delete it. A version cannot be modified if there are versions derived from it. That is, if a child version is derived from a transient version, the parent transient version is automatically upgraded to a working version.

126

VERSANT Database Fundamentals Manual

Get version status c c++ o_getvsnstatus() getvsnstatus()

Set version status c c++ o_setvsnstatus() setvsnstatus()

Get version You can bring a versioned object into memory using its version number or version status.

Get version c c++ o_locatevsn() locatevsn()

Get default version Set default version Get generic object Is generic object When you create the first version of an object, the original object becomes the root of the object's version graph and a generic object instance is created. The generic object stores the version derivation graph for a versioned object and also stores the version number of the default version. There is one generic object instance for each versioned object. When the last version in a version tree for a database is deleted, the generic version is also deleted, even if some versions have been checked out. When you get a versioned object (with a "locate object" routine or by dereferencing it,) the generic object is brought into the object cache along with the versioned object. If the default version number is greater than zero, the default version is statically bound to the corresponding version of the object. If the default version number is less than zero, representing most recent transient version, most recent working version, most recent released version, or most recent version, then the default version is dynamically bound at run time to the corresponding versioned object instance. Initially the default version number is the most recent version in the derivation graph. You can set this
127

VERSANT Database Fundamentals Manual

number explicitly with the "set default version" routine. An application can statically bind to any version of an object, including the default version. Making a new version automatically locks the generic object which contains the version graph. Until the lock on the generic object is released, an application using the generic object to dynamically bind to the default version is locked out. This short lock is released at the end of the short transaction. Review your applications to see if they access objects that have been or will be versioned. Unless you want to create new versions with each checkin, you may need to change your application code to either statically bind to a specific version or dynamically bind to the default version.

Get default version c c++ o_getdefaultvsn() getdefaultvsn()

Set default version c c++ o_setdefaultvsn() setdefaultvsn()

Get generic object c c++ o_getgeninst() getgeninst()

Is generic object c++ c o_isgeninst() isgeninst()

128

VERSANT Database Fundamentals Manual

Delete version You can delete a versioned object without removing its description in the version graph. Alternately, you can delete an entire hierarchy by deleting the generic instance.

Delete version c c++ o_deletevsn() deletevsn()

Get version number You can get the version number of a version instance. If the instance involved is a generic instance, the version number of the current default version is returned.

Get version number c c++ o_getvsnno() getvsnno()

Versioning Example
Version management across database boundaries Following is an example of version management involving three databases, a personal database, db1, a group database, db2, and a personal database, db3. The example shows the coordination of versions among databases for a single object with multiple versions.

129

VERSANT Database Fundamentals Manual

In the above example, there are three version derivation hierarchies corresponding to two personal databases and a group database. The original object becomes, through checkouts and checkins, three different versioned objects, one in each database. The Version Manager uses virtual link information to maintain a derivation history across the databases. t0 t1 t2

At time zero there is one version object, db1/v1, in personal database one. At time one a child version object, db1/v2, is created. At time two, the child version in database one, object db1/v2, is checked into the group database as object db2/v1. Because object db1/v2 is a versioned object, the checkin does not delete it from the personal database. To illustrate parallel version derivation, at time three a second child version of the object in database one is created as object db1/v3. This object is a sibling to object db1/v2 and shares the parent object db1/v1. At time four, the child version in group database two, is checked out from the group database into another personal database as object db3/v1. At time five, a child version is created in the second personal database as object db3/v2.

t3

t4

t5

130

VERSANT Database Fundamentals Manual

t6

At time six, a child version is created in the first personal database as object db1/v4. Its parent is db1/v2. At time seven, a parallel child version is created in the second personal database as object db3/v3. This object is a sibling to object db3/v2 and shares the parent object db3/v1. At time eight, a child version, object db3/v4, is created in the second personal database with parent object db3/v2 and grandparent object db3/v1. At time nine, the child version object db3/v4 is checked into the group database. The checkin creates a version object db2/v2 from the parent object db2/v1. The Version Manager chooses as a parent object db2/v1 by traversing up the derivation hierarchy for the second personal database db3 and finding that the grandparent object db3/v1 was derived from object db2/v1 in the group database. Because the checked in object is new, it becomes a new version, object db2/v2, in database two.

t7

t8

t9

t10

At time ten, a similar situation occurs when the latest version in the group database, object db2/v2, is checked out to the first personal database. Again, the Version Manager traverses up the derivation hierarchy to find that the parent object db2/v1 was derived from object db1/v2. Thus, in personal database one, object db1/v2 is made the parent of the checked-out object, which becomes object db1/v5.

131

VERSANT Database Fundamentals Manual

Configuration Management
Overview
VERSANT configuration management is a low-level framework upon which you can build a higher-level configuration management system with policies appropriate for each of your applications. VERSANT configuration management has a "smart object" architecture for versioning objects. Smart objects serve as intelligent proxies, which, when dereferenced yield the correct version of the original objects (e.g. the latest or released). Smart objects are useful when large composite objects require versioning of individual components and it is not practical to maintain multiple versions for the entire object. Smart Objects contain two important features: • A configuration table A configuration table links smart objects to specific object versions. • A resolve function A resolve function processes the configuration table to return the specific version based on your current configuration. This is similar to implementing a many-to-many association, except that only one pair of the association is valid for any specific configuration. Important Note — While configuration management can be used to build a versioning scheme, it is completely different from VERSANT versioning and has no dependence on it. When we talk about versions in a configuration, we actually mean that we have different objects (non-versioned, with no generic object or version tree) whose only connection is that they are pointed to by the same smart object. The smart object connects these objects together logically, indicating that they contain different versions of the same logical data. In a configuration, a member object is just a regular object, not a versioned object with a generic object and version graph. Following are key terms related to configuration management. Configuration Object — A configuration object is an object that you define to identify a unique configuration. Configuration objects are normally developed in a tree hierarchy that identifies all configurations associated
132

VERSANT Database Fundamentals Manual

within a configuration management scheme. Configuration List — A configuration list is an ordered list of configuration objects which specifies the order used when binding a reference from a smart object to a target object. To make resolution of higher priority items faster, the configuration lists are in reverse order of priority, with the highest priority configuration appearing last. A configuration list and a smart object are required to resolve a target object or versioned object. Configuration Table — A configuration table links configuration objects with the member objects in a smart object. Member Object — A member object is an object associated with a specific smart object. A member object can be associated with at most one smart object. Member List — A member list is the set of member objects that associated by one or more similarities and are linked to a single smart object. For example, member objects may have the same parent. A member list typically contains versions of a single, specific object. Target Object — A target object is the object resolved dynamically based your priority scheme (configuration list) and the configuration table in the smart object. Smart Object — A smart object (C interface) or smart link (C++ interface) is an object that dynamically binds a configuration object to a target object. This binding is done at run time, based on the configuration list specified by the user. Management Application — A management application manages the configurations and smart objects. Most of the functions and methods described in this document are used only by a management application. User Application — A user application uses configuration lists and smart objects, to dynamically resolve the target objects.

Architecture
Smart Object Model
A smart object (S1) can be conceptually modeled with the following table.

133

VERSANT Database Fundamentals Manual

Configuration
C1 C2 NULL C3

Target Object
T1 T2 T3 T1 T4 T5

Notice that there are two different ways that targets can be specified as members without mapping them to a configuration. The first way is to specify a NULL configuration, as is the case with T3. The second way is to take advantage of the fact that the two columns are implemented as two separate vstrs. This allows you to make the target column longer than the configuration column and store the unmapped targets in the extra portion of the target column. In the above, T4 and T5 are specified as

unmapped members. Since you are responsible for managing the table, you can decide on a target by target basis which of these two methods to use.

Smart Object Operations
Although there are many operations on the smart object, most of them are standard methods such as creation or get and put for the attributes. The only unique method is the "resolve" operation. Resolving — Resolving is the process by which a smart object is dynamically bound to a target object in the context of a configuration list. You can think of it as a function which maps a smart object and a configuration list to a target object. It is defined just as you might expect when you consider that a configuration list is a prioritized list of configurations: resolve(smart object S, configuration list L) returns target object { configuration C = highest priority in L with an entry in the S table return the target object T associated with C in the S table }

The most simple and general purpose algorithm for implementing the resolve operation is a nested loop of order MN, where M is the size of the configuration list and N is the size of the smart object's table: for (L in configuration list, highest priority first) for (configurations T in table) if (L == T) return target associated with T return NULL

Since this could become expensive during heavy dereferencing, two optimizations to this algorithm are
134

VERSANT Database Fundamentals Manual

available. Resolve can be described by considering the smart object S1. If S1 is resolved with the configuration list {C1, C2, C4}, it would resolve the target object T2. Note that the highest priority, C4, was not associated with a target object in S1. Since C2 was associated with T2, it was not necessary to look for a match with to a lower priority configuration such as C1.

Optimize Caching
Each smart object caches the most recent result of the resolve operation. This is highly effective on the front end where normally a single configuration list is used repeatedly for long periods of time.

Optimize Hash Table
The VERSANT ODBMS configuration management concept incorporates a small hash table for each configuration list which maps configurations to their position in the list. Using this hash table, we can implement the following linear time algorithm: for (configurations T in table) if (priority(T) is defined && priority(T) is the highest priority so far) result = T

You can further optimize this algorithm if you are willing to accept the following restriction: • The relative order of the configurations in the configuration lists and in the tables of smart objects must always be the same.

In other words, the entries in the tables must be sorted in order of increasing configuration priority. This implies that the first case where priority (Tx) is defined is also the highest priority. This being the case, the loop can be modified to terminate early as follows: for (configurations T in table, highest priority first) if (priority(T) is defined) return T return NULL

Since you may or may not feel the extra optimization is worth the restriction, the option to specify whether or not the restriction has been accepted is provided.

Smart Object Forwarding
The concept of smart object forwarding aids in the merging of two smart objects. A smart object can be instructed to forward its resolve operations to another smart object by placing a special value in its table. For example to forward S2 to S1, the contents of S2's table could be merged into S1 and the table of S2 could
135

VERSANT Database Fundamentals Manual

then be set as follows: Configuration
S2

Target Object
S1

To avoid the expense associated with an extra level of indirection, the user can replace references to S2 with references to S1 as they are encountered, in a lazy incremental fashion. You may also consider using queries to preemptively find and fix objects that reference S2. Since such an operation can be expensive, it can be done in the background during non-peak time periods. Forwarding can easily be limited to one level by resolving multiple levels of forwarding at merge time.

Locking
Smart objects are read with the default lock mode. This implies that the query and gwrite remote procedure calls send the default lock to the backend. To avoid deadlock, the standard order for obtaining locks is smart object first, target object next. In the forwarding case where there are multiple smart objects, locks are obtained in order, following the forwarding chain. Query is an exception to this rule, it reads the target first but has special logic to avoid deadlock.

Optimistic Locking
The smart objects can come under heavy contention in a multi-user environment. To increase system performance a timestamp attribute is provided to support optimistic locking. To prevent potential deadlocks, you must specify the smart objects before the target objects when performing a group read. When a group write is performed the objects are partitioned into two groups: smart objects and non-smart objects. Locks are first obtained for the smart objects. Group read makes the assumption that you have specified the smart objects first and then the targets. If this is not done there can be a deadlock. For more information on optimistic locking refer to the VERSANT Database Fundamentals Manual.

Query Support
Each member object maintains a backpointer to its smart object to accommodate execution of a query for a particular configuration list. Since you maintain the smart object's, you must also maintain the backpointer via a VERSANT supplied API. This API implements a "set smart object" operation and must be invoked by the user whenever a member is added to or removed from a smart object. If you are not interested in using the query support, you can choose to save space by not maintaining the backpointer. In this case, you can also elect to store only the members that are associated with a configuration
136

VERSANT Database Fundamentals Manual

object in a smart object's table. You can also decide whether to return matches that are not bound to a smart object by setting a flag to the select APIs. If you want to resolve the smart objects returned as a result of your query, specify the O_CM_RETURN_TARGETS option in your query.

Configuration Lists
The configuration list model can be used to implement an efficient delta versioning system. For example, consider the scenario where you are changing 10 objects in a database of 100,000 "released" objects. A configuration object C1 can represent the original unchanged configuration of the database and C2 can represent your new configuration. To test the configuration changes, set your configuration list to {C1, C2} and update the tables in the smart objects of your 10 changed objects to map C2 to the new objects in addition to the original mapping of C1 to the old objects. Users without access to the changes would keep their configuration list set to {C1}. In the future, if you wanted to make an additional change to 1 of your 10 changed objects, you could create a new configuration C3, set your configuration list to {C1, C2, C3}, and add an entry mapping C3 to the new version of the target object. Later you might want to make changes to 5 more previously unchanged objects (configuration C1). You would then map the four configuration {C1, C2, C3, C4} and the database into a tree similar to the following illustration:

The path from the current version (C3) to the original root version (C1) would then be used as the
137

VERSANT Database Fundamentals Manual

configuration list {C1, C2, C3}. Notice that the number of smart objects with entries for a particular version tends to be much greater for the lower priority configuration objects than for the high ones. In our example, there were 100,000 smart objects with entries for C1, 10 smart objects with entries for C2, and 1 smart object with an entry for C3. This makes sense when you think of C1 as a root configuration shared by everyone, and C3 as a leaf configuration representing a small change used by one person.

Usage
Session Options
Routines C/VERSANT C++/VERSANT o_beginsession() PDOM::beginsession()

Configuration management options To use configuration management routines, you must specify one or both of the following in the options parameter, or you will get the error OM_CM_WRONG_MODE.
O_CONFIG O_CONFIG_ORDERED

Enable configuration management routines. Assume that the configurations in configuration lists and tables of smart objects are always in the same relative order.

Each session has a default configuration list associated with it. When NULL is passed to a routine which takes a configuration list, or when a routine involves a configuration list but provides no way to specify one, this default configuration list is used. Until you set it otherwise, the default configuration list is NULL.

Query and Group Read Options
Configuration management can improve performance by avoiding unnecessary reading of objects. Routines C/VERSANT o_greadobjs() o_pathselect() o_pathselectcursor()

NOTE: you cannot use the following configuration management options in: o_select(), because o_select() does not take a query option.

138

VERSANT Database Fundamentals Manual

C++/VERSANT

PDOM:greadobjs() PDOM::select_with_vstr() PClass:select() VCursor::VCursor()

Configuration management options If you have enabled configuration management when you started your session, you can specify one or more of the following in the options parameter. Before doing a select, you must make sure that the appropriate smart objects are flushed in addition to instances of the class being selected.
O_CM_VALIDATE

If specified, a server performing a query or group read will return to the client application an object that satisfies the find or get criteria: 1. 2. 3. if it is a smart object. if it is the target of a smart object. if it does not have a smart object.

An object will not be returned if it has a smart object but is not a target of its smart object when resolved with the default configuration list.
O_CM_MUST_HAVE_SMART

If specified, a server performing a query or group read will return an object that satisfies the find or get criteria: 1. 2. if it is a smart object. if it has a smart object (it does not have to be a target of a smart object, it just has to have a smart object.)

An object will not be returned if does not have a smart object.
O_CM_RETURN_TARGETS

If specified, a server performing a query or group read will: 1. 2. resolve smart objects that satisfy the find or get criteria and only return target objects. return objects that satisfy the find or get criteria if they do not have a smart object.

If used with O_CM_MUST_HAVE_SMART, then only objects that have smart objects will be returned. If used with O_CM_VALIDATE, then only targets that are results of the resolve operation on their smart objects will be returned.
139

VERSANT Database Fundamentals Manual

O_CM_DONT_RESOLVE

If specified, a server performing a query or group read will not resolve a smart object. By default, when a smart object is encountered, the server will resolve it in the default configuration and return both the original smart object and the resulting target object.

Thread Options
Routines C/VERSANT C++/VERSANT o_setthreadoptions() VSession:setthreadoptions()

Configuration management options If you have enabled configuration management when you started your session, you can specify one or more of the following in the options parameter.
O_CONFIG_RESOLVE

If specified for a thread, smart objects will be transparently resolved when passed an argument to functions.
O_DROP_RLOCK_TIMESTAMP_ONLY

If specified for a thread, a group read or single object fetch will obtain a read lock on all fetched objects and then, when the entire read has finished, drop the read locks on smart objects and on objects containing a time stamp. This option can be used only in an optimistic locking session. If used in a strict locking session, it will return an error. The purpose of this option is to ensure that a group of objects are read consistently in an optimistic locking session. Because a read lock is applied during the duration of the operation, a lock conflict can occur even in an optimistic locking session. If smart objects are involved, the following occurs to the smart objects: 1. 2. 3. The smart objects are fetched, and the read locks are dropped. The smart objects are resolved. The target objects are read (without read locks.)

During the time between the dropping of locks on the smart objects and the time of the resolve operation, there is a window of time during which the smart objects could be modified by
140

VERSANT Database Fundamentals Manual

another transaction, which would invalidate the resolve operation. The following methodology represents one way safely to update optimistically locked smart objects. 1. 2. Turn the O_DROP_RLOCK_TIMESTAMP_ONLY option off and set the default lock mode to write lock. Call a check timestamps routine (o_checktimestamps() in C) on all dirty smart objects. This will place a write lock on all the edited smart objects and return a list of objects that are out of date. Refresh the out-of-date, dirty smart objects . Re-apply your edits to the objects that have been refreshed. Commit the changes Turn the O_DROP_RLOCK_TIMESTMP_ONLY option on and reset the default lock mode.

3. 4. 5. 6.

Configuration Management Routines
C/VERSANT
o_cmgetconfiglist() o_cmgetsmartobject() o_cmgettable() o_cminvalidatecache() o_cmissmartobject() o_cmnewsmartobject() o_cmresolve () o_cmsetconfiglist() o_cmsetsmartobject()

Get the default configuration list. Get smart object. Get configuration table. Invalidate cache entries related to a smart object. Is this a smart object. Create a smart object. Resolve smart object. Set the default configuration list. Set smart object.

C++/VERSANT
Link::get_configurations() Link::get_targets() Link::invalidate_cache() Link::is_smart() Link::resolve() Link::new_smart() Link::resolve_target()

Get configuration objects. Get target objects. Invalidate cache entries related to a smart obj. Is this a smart object. Resolve smart object. Create a smart object. Resolve smart object.
141

VERSANT Database Fundamentals Manual

PDOM::gdeleteobjs() PDOM::get_configuration_list() PDOM::set_configuration_list() PObject::get_smart() PObject::set_smart()

Delete smart or member objects. Get the default configuration list. Set the default configuration list. Get smart object. Set smart object.

Standard Routines that Can Respond to Smart Objects
C/VERSANT
o_acquireplock()

o_checktimestamps()

o_classnameof() o_classobjof() o_cleardirty() o_compareobj() o_deleteobj() o_downgradelock() o_downgradelocks()

o_findremoteobj() o_gdeleteobjs() o_getattr() o_getattroffset() o_getattrpos()

If one or more of the objects specified are smart, transparently apply the resolve operation on them and acquire the lock on their targets. Determine the objects that have changed since copies have been read into the object cache. If some of the objects are smart, resolve them and check if either of the smart or target objects have been modified. Retrieve the class name of the result of the resolve on the smart object. Retrieve the class object of the result of the resolve on the smart object. Mark as clean the target of the resolve. Resolve the smart object and apply the compare operation on the result. Resolve the smart object and delete the result. Downgrade the lock on the target object. If some of the objects specified are smart, downgrade or release locks on the smart objects as well as their resolves without flushing them from the application cache. Return the name of the database that contains the result of the resolve operation. Resolve the smart objects and delete the results. Retrieve the value of the attribute from the result of the resolve. From the result of the resolve, retrieve the attribute value whose offset is specified as one of the arguments. From the result of the resolve, retrieve the attribute value whose position is specified as one of the arguments.

142

VERSANT Database Fundamentals Manual

o_getclosure()

o_iseqobj() o_isinstanceof() o_locateobj() o_migrateobj() o_migrateobjs() o_moveobjs() o_preptochange() o_refreshobj()

o_refreshobjs()

o_releaseobj() o_releaseobjs() o_setattr()

o_setattroffset()

o_setattrpos()

o_setdirty() o_unpinobj()

Evaluate the objects objs in the database dbname and for the number of levels specified as levels follow all links to their target objects. If a returned object is a smart object, then follow the links from the result of the resolve operation. Resolve the objects if they are smart and apply the operation on the results. Return TRUE if the result of the resolve is an instance of the class specified as one of the arguments. Resolve smart object and get target object. Move the smart object and all the member objects associated with it to the new database. Move the smart object and all the member objects associated with it to the new database. Move the smart object and all the member objects associated with it to the new database. Mark as dirty the target of the resolve operation on the smart object. Update the smart object and the result of its resolve in the object memory cache with their current state in the source database. Update the smart object and the result of its resolve in the object memory cache with their current state in the source database. Release the memory space used by the target of the resolve operation on the smart object. Release the memory space used by the target of the resolve operation on the smart object. Set a write lock on the target of the resolve if it does not already have one, mark it as dirty, and set the specified attribute to the new value in the specified buffer. Set a write lock on the target of the resolve operation if it does not already have one, mark the object as dirty, and set the attribute whose offset is offset to the new value in the buffer specified as buffer. Set a write lock on the result of the resolve on smart if it does not already have one, mark the object as dirty, and set the attribute with the specified position to the new value in the buffer specified as buffer. Mark as dirty the target of the resolve operation on the smart object. Clear any pins on the smart object and the result of its resolve that have been set in the current pin region.
143

VERSANT Database Fundamentals Manual

o_upgradelock() o_xactwithvstr()

Upgrade the lock on smart and the result of its resolve to the specified lock mode and options. Commit, checkpoint commit, or rollback changes to objects in the session database. If the smart objects are not dirty, operate only on the results of their resolve; otherwise, operate on both.

C++/VERSANT
Link::operator->() Link::operator*() Link::migrateobj() Link::setattr()

Link::unpinobj() LinkAny::deleteobj() LinkAny::migrateobj() LinkAny::setattr()

LinkAny::unpinobj() PDOM::acquireplock()

PDOM::checktimestamps()

PDOM::downgradelock() PDOM::downgradelocks()

PDOM::gdeleteobjs() PDOM::getclosure()

Resolve smart object and get target object. Resolve smart object and cast link to target object. Move the smart object and all the member objects associated with it to the new database. Set a write lock on the target of the resolve if it does not already have one, mark it as dirty, and set the specified attribute to the new value in the specified buffer. Clear any pins on the smart object and the result of its resolve that have been set in the current pin region. Delete smart and target object. Move the smart object and all the member objects associated with it to the new database. Set a write lock on the target of the resolve if it does not already have one, mark it as dirty, and set the specified attribute to the new value in the specified buffer. Clear any pins on the smart object and the result of its resolve that have been set in the current pin region. If one or more of the objects specified are smart, transparently apply the resolve operation on them and acquire the lock on their targets. Determine the objects that have changed since copies have been read into the object cache. If some of the objects are smart, resolve them and check if either of the smart or target objects have been modified. Downgrade the lock on the target object. If some of the objects specified are smart, downgrade or release locks on the smart objects as well as their resolves without flushing them from the application cache. Delete smart and target objects. Evaluate the objects objs in the database dbname and for the specified number of levels follow all links to their target objects. If a returned object is a smart object, then follow the links from the result of the resolve operation.

144

VERSANT Database Fundamentals Manual

PDOM::refreshobj()

PDOM::refreshobjs() PDOM::refreshobjs()

PDOM::releaseobjs() PDOM::upgradelock()

PDOM::xactwithvstr()

PObject::migrateobj() PObject::migrateobjs() PObject::unpinobj()

Update the smart object and the result of its resolve in the object memory cache with their current state in the source database. Release the memory space used by the target of the resolve operation on the smart object. Update the smart object and the result of its resolve in the object memory cache with their current state in the source database. Release the memory space used by the target of the resolve operation on the smart object. Upgrade the lock on the smart object and the result of its resolve to the specified lock mode with the specified options. Commit, checkpoint commit, or rollback changes to objects in the session database. If the smart objects are not dirty, operate only on the results of their resolve; otherwise, operate on both. Move the smart object and all the member objects associated with it to the new database. Move the smart object and all the member objects associated with it to the new database. Clear any pins on the smart object and the result of its resolve that have been set in the current pin region.

Example Demo Program
For the demonstration program three higher level APIs developed on top of o_cmgettable(), o_cmsetsmart() and o_cminvalidatechache. The demo APIs are: o_cmaddconfig() o_cmremoveconfig() o_cmsetconfig() /* * * * * */

cmdemo.c: Demo/example for implementing Configuration Management tests.

#include #include /* * *

o_cmaddconfig: Add the specified (config, target) pair to smart's table at a specified position. A position 145

VERSANT Database Fundamentals Manual

* * */

of -1 indicates that the entry should be added at the end of the table with the highest priority.

o_err o_cmaddconfig ( o_object smart, o_object config, o_object target, o_4b position ) { o_err err; o_vstr *configVstr; o_vstr *targetVstr; o_object *newConfigObjects; o_object *newTargetObjects; o_4b configVstrSize; o_4b targetVstrSize; o_4b i;

/* Get the Configuration and Target Vstrs for smart */ err = o_cmgettable(smart, &configVstr, &targetVstr, TRUE); if (err != O_OK) return err; /* get the sizes of the vstrs */ configVstrSize = o_sizeofvstr(configVstr); targetVstrSize = o_sizeofvstr(targetVstr);

/* * Create the new config/target object list */ newConfigObjects = (o_object *)malloc(configVstrSize + sizeof(o_object)); if (newConfigObjects == NULL) return o_errno; newTargetObjects = (o_object *)malloc(targetVstrSize + sizeof(o_object)); if (newTargetObjects == NULL) return o_errno; /* Insert the pair at the end of the table if position == -1 */ /* (the following assumes that the configuration list and the */ /* target list have the same length, which not true in general.) */ 146

VERSANT Database Fundamentals Manual

if (position == -1) { /* Construct the new list of configuration objects */ for (i=0; i < configVstrSize/sizeof(o_object); i++) { newConfigObjects[i] = ((o_object *)*configVstr)[i]; } /* Insert config at the end of the configuration list */ newConfigObjects[i] = config; /* Construct the new list of target objects */ for (i=0; i < targetVstrSize/sizeof(o_object); i++) { newTargetObjects[i] = ((o_object *)*targetVstr)[i]; } /* Insert target at the end of the target list */ newTargetObjects[i] = target; } else { /* Insert config object at the specified position */ for (i=0; i < position; i++) { newConfigObjects[i] = ((o_object *)*configVstr)[i]; } newConfigObjects[i] = config; for(i=position; i < configVstrSize/sizeof(o_object); i++) { newConfigObjects[i+1] = ((o_object *)*configVstr)[i]; } /* Insert target object at the specified position */ for (i=0; i < position; i++) { newTargetObjects[i] = ((o_object *)*targetVstr)[i]; } newTargetObjects[i] = target; for(i=position; i < targetVstrSize/sizeof(o_object); i++) { newTargetObjects[i+1] = ((o_object *)*targetVstr)[i]; } }

/* Reset smart's table */ *configVstr = o_newvstr(configVstr, configVstrSize+sizeof(o_object), (o_u1b *)newConfigObjects); 147

VERSANT Database Fundamentals Manual

*targetVstr = o_newvstr(targetVstr, targetVstrSize+sizeof(o_object), (o_u1b *)newTargetObjects); /* dirty the smart object */ err = o_preptochange(smart); if (err != O_OK) return err; /* unpin the smart object */ err = o_unpinobj(smart, TRUE); if (err != O_OK) return err; free(newConfigObjects); free(newTargetObjects); return O_OK; } /* * o_cmremoveconfig : Remove the entry associated with config from * smart's table. If there is a target associated * with config, make sure that the target is not * removed from smart's target array. */ o_err o_cmremoveconfig ( o_object smart, o_object config ) { o_vstr *configVstr; o_vstr *targetVstr; o_err err = O_OK; o_4b i; /* Get smart's table */ err = o_cmgettable(smart, &configVstr, &targetVstr, TRUE); if (err != O_OK) return err; /* Look for config in smart's config table */ for (i=0; i < o_sizeofvstr(configVstr)/sizeof(o_object); i++) { /* If the object is found, set it to NULL */ if (config == ((o_object *)*configVstr)[i]) { ((o_object *)*configVstr)[i] = (o_object)NULL; 148

VERSANT Database Fundamentals Manual

break; } } /* dirty the smart object */ err = o_preptochange(smart); if (err != O_OK) return err; /* unpin the smart object */ err = o_unpinobj(smart, TRUE); return err; /* Object not found if this point is reached */ } /* * o_cmsetconfig: Sets the target associated with config in smart's * table, making sure that the old target is not removed * from smart's target array. */ o_err o_cmsetconfig ( o_object smart, o_object config, o_object target ) { o_err err = O_OK; o_vstr *configVstr; o_vstr *targetVstr; o_object oldTarget; o_object oldConfig; o_4b i; /* Get the Configuration and Target Vstrs for smart */ err = o_cmgettable(smart, &configVstr, &targetVstr, TRUE); if (err != O_OK) return err; /* Search for config in smart's configuration table */ for (i=0; i < o_sizeofvstr(configVstr)/sizeof(o_object); i++) { /* * If the object is found, set its target object. Make sure that * you save the previous target object */ if (config == ((o_object *)*configVstr)[i]) { /* Save the old target object in a temporary variable */ 149

VERSANT Database Fundamentals Manual

oldTarget = ((o_object *)*targetVstr)[i]; /* Set the target object associated with config to target */ ((o_object *)*targetVstr)[i] = target; /* * Insert the old target at the end of the target vstr. * Associate this target object with a NULL configuration * object */ oldConfig = (o_object)NULL; err = o_cmaddconfig(smart, oldConfig, oldTarget, -1); if (err != O_OK) return err; return O_OK; } } /* dirty the smart object */ err = o_preptochange(smart); if (err != O_OK) return err; /* unpin the smart object */ err = o_unpinobj(smart, TRUE); return err; } o_err defineClasses(char *dbname) { o_object schema; /* statically set up stuff for o_defineclass */ static o_attrdesc attrs[] = { { "x", { "", "" }, "o_4b", O_SINGLE, NULL, 0, NULL }, { "y", { "", "" }, "o_4b", O_SINGLE, NULL, 0, NULL }, { "z", { "", "" }, "o_4b", O_SINGLE, NULL, 0, NULL } }; static o_attrdesc *attrPtrs[] = { &attrs[0], &attrs[1], &attrs[2] }; /* copy it to a vstr */ o_vstr attrsVstr = o_newvstr(&attrsVstr, sizeof(attrPtrs), (o_u1b *)attrPtrs); if (attrsVstr == NULL) return o_errno; /* create the class */ 150 /* Error if this point is reached */

VERSANT Database Fundamentals Manual

schema = o_defineclass("point", dbname, NULL, attrsVstr, NULL); if (schema == NULL && o_errno != SCH_CLASS_DEFINED) return o_errno; /* free vstr */ o_deletevstr(&attrsVstr); return O_OK; } void main(int argc, char **argv) { o_err err; o_opts opts; o_object smart, target, forwardedSmart; char *dbname; o_bool isSmart; o_object configObjects[10]; /* The configuration objects */ o_object targetObjects[10]; /* The target objects */ /* parse args */ if (argc != 2) { printf("usage: %s \n", argv[0]); return; } dbname = argv[1]; /* begin the session */ printf("o_beginsession\n"); opts[0] = O_CONFIG ; err = o_beginsession(NULL, dbname, NULL, opts); if (err != O_OK) goto error; /* define the classes */ printf("defineClasses\n"); err = defineClasses(dbname); if (err != O_OK) goto error; /* populate database */ { o_4b i; /* create the configuration objects */ for (i = 0; i < sizeof(configObjects)/sizeof(o_object); ++i) { configObjects[i] = o_createobj("point", NULL, TRUE); if (configObjects[i] == NULL) { 151

VERSANT Database Fundamentals Manual

err = o_errno; goto error; } } /* create the target objects */ for (i = 0; i < sizeof(targetObjects)/sizeof(o_object); ++i) { targetObjects[i] = o_createobj("point", NULL, TRUE); if (targetObjects[i] == NULL) { err = o_errno; goto error; } } /* create a new smart object */ printf("o_cmnewsmartobject\n"); err = o_cmnewsmartobject(&smart, dbname, TRUE); if (smart == NULL) { err = o_errno; goto error; } } /* set up smart's table */ { o_4b i; o_vstr *configVstr; o_vstr *targetVstr; printf("o_cmgettable\n"); err = o_cmgettable(smart, &configVstr, &targetVstr, TRUE); if (err != O_OK) goto error; /* Set up smart's table */ { *configVstr = o_newvstr(configVstr, sizeof(configObjects), (o_u1b *)configObjects); *targetVstr = o_newvstr(targetVstr, sizeof(targetObjects), (o_u1b *)targetObjects); } err = o_preptochange(smart); if (err != O_OK) goto error; /* unpin the smart object */ 152

VERSANT Database Fundamentals Manual

err = o_unpinobj(smart, TRUE); if (err != O_OK) goto error; /* make sure objects aren't cached */ err = o_xact(O_COMMIT, "cmtest"); if (err != O_OK) goto error; /* Make sure smart's table has been set up properly */ { o_vstr *configTestVstr; o_vstr *targetTestVstr; err = o_cmgettable(smart, &configTestVstr, &targetTestVstr, FALSE); if (err != O_OK) goto error; /* compare to what we put in */ for (i = 0; i < sizeof(configObjects)/sizeof(o_object); ++i) if ((((o_object *)*configTestVstr)[i] != configObjects[i]) || (((o_object *) *targetTestVstr)[i] != targetObjects[i])) printf(" Error in o_cmgettable\n"); } } /* test demo APIs */ { /* define the new (config, target) pairs */ o_object config1 = o_createobj("point", NULL, o_object target1 = o_createobj("point", NULL, o_object config2 = o_createobj("point", NULL, o_object target2 = o_createobj("point", NULL,

TRUE); TRUE); TRUE); TRUE);

/* test o_cmaddconfig */ { /* insert the (config1, target1) pair into smart's table */ printf("o_cmaddconfig, 6\n"); err = o_cmaddconfig(smart, config1, target1, 6); if (err != O_OK) goto error; /* make sure objects aren't cached */ err = o_xact(O_COMMIT, "cmtest"); if (err != O_OK) goto error;

153

VERSANT Database Fundamentals Manual

/* check to make sure o_cmaddconfig works properly */ { o_vstr *configTestVstr; o_vstr *targetTestVstr; /* get smart's table */ err = o_cmgettable(smart, &configTestVstr, &targetTestVstr, FALSE); if (err != O_OK) goto error; /* verify if the config/target pair is present in the table */ if ((((o_object *)*configTestVstr)[6] != config1) || (((o_object *)*targetTestVstr)[6] != target1)) printf(" Error in o_cmaddconfig\n"); } } /* * re-test o_cmaddconfig, this time inserting items at the end * of the table */ { /* insert the (config2, target2) pair into smart's table*/ printf("o_cmaddconfig, -1\n"); err = o_cmaddconfig(smart, config2, target2, -1); if (err != O_OK) goto error; /* make sure objects aren't cached */ err = o_xact(O_COMMIT, "cmtest"); if (err != O_OK) goto error; /* check to { o_vstr o_vstr o_4b o_4b make sure o_cmaddconfig works properly */ *configTestVstr; *targetTestVstr; configVstrSize; targetVstrSize;

/* get smart's table */ err = o_cmgettable(smart, &configTestVstr, &targetTestVstr, FALSE); if (err != O_OK) goto error; configVstrSize = o_sizeofvstr(configTestVstr)/sizeof(o_object); 154

VERSANT Database Fundamentals Manual

targetVstrSize = o_sizeofvstr(targetTestVstr)/sizeof(o_object); /* verify if the config/target pair is present in the table */ if ((((o_object *)*configTestVstr)[configVstrSize-1] != config2) || (((o_object *) *targetTestVstr)[targetVstrSize-1] != target2)) printf(" Error in o_cmaddconfig\n"); } } /* test o_cmremoveconfig */ { printf("o_cmremoveconfig\n"); /* remove config2 from smart's table */ err = o_cmremoveconfig(smart, config2); if (err != O_OK) goto error; /* make sure objects aren't cached */ err = o_xact(O_COMMIT, "cmtest"); if (err != O_OK) goto error; /* check to { o_vstr o_vstr o_4b o_4b make sure o_cmremoveconfig works properly */ *configTestVstr; *targetTestVstr; configVstrSize; targetVstrSize;

/* get smart's table */ err = o_cmgettable(smart, &configTestVstr, &targetTestVstr, FALSE); if (err != O_OK) goto error; configVstrSize = o_sizeofvstr(configTestVstr)/sizeof(o_object); targetVstrSize = o_sizeofvstr(targetTestVstr)/sizeof(o_object); /* verify if config2 has been removed */ if ((((o_object *)*configTestVstr)[configVstrSize-1] != NULL)|| (((o_object *) *targetTestVstr)[targetVstrSize-1] != target2)) printf(" Error in o_cmremoveconfig\n"); } 155

VERSANT Database Fundamentals Manual

} /* test o_cmsetconfig */ { o_object newTarget = o_createobj("point", NULL, TRUE); /* set the target associated with config1 */ printf("o_cmsetconfig\n"); err = o_cmsetconfig(smart, config1, newTarget); if (err != O_OK) goto error; /* make sure objects aren't cached */ err = o_xact(O_COMMIT, "cmtest"); if (err != O_OK) goto error; /* check to { o_vstr o_vstr o_4b o_4b o_4b make sure o_cmsetconfig works properly */ *configTestVstr; *targetTestVstr; configVstrSize; targetVstrSize; i;

/* get smart's table */ err = o_cmgettable(smart, &configTestVstr, &targetTestVstr, FALSE); if (err != O_OK) goto error; configVstrSize = o_sizeofvstr(configTestVstr)/sizeof(o_object); targetVstrSize = o_sizeofvstr(targetTestVstr)/sizeof(o_object); /* Check if the target associated with config1 is newTarget */ for (i = 0; i < configVstrSize; ++i) { if (((o_object *)*configTestVstr)[i] == config1) { if (((o_object *)*targetTestVstr)[i] != newTarget) printf(" Error in o_cmsetconfig\n"); break; } } /* Check if the last item in the target table is target1 */ 156

VERSANT Database Fundamentals Manual

i = targetVstrSize; if (((o_object *)*targetTestVstr)[i-1] != target1) printf(" Error in o_cmsetconfig \n"); /*Check if the last item in the config table is NULL*/ i = configVstrSize; if (((o_object *)*configTestVstr)[i-1] != (o_object)NULL) printf(" Error in o_cmsetconfig \n"); } } } /* end the session */ printf("o_endsession\n"); err = o_endsession(NULL, NULL); if (err != O_OK) goto error; return; error: { printf(" => err #%ld\n", err); return; }

}

157

VERSANT Database Fundamentals Manual

Chapter 9: Object Sharing
Mixing C and C++ Code and Objects.............................................................................................. 159 Storage Transform Concepts...................................................................................................... 162 Storage Transforms for Elemental Data Types .............................................................................. 162 Storage Transforms for Special Embedded Types ......................................................................... 164 Storage Transforms for Fixed Array Types ................................................................................... 164 Storage Transforms for Vstr Types .............................................................................................. 165 Object Sharing Methods ........................................................................................................... 166

158

VERSANT Database Fundamentals Manual

Mixing C and C++ Code and Objects
The best way to handle objects created with C++/VERSANT is with C++ applications. The best way to handle objects created with C/VERSANT is with C applications. To handle both C and C++ objects in the same application, the easiest way is to write in C++ and use the C++ interface to handle the C++ objects and simultaneously use the C Interface to handle the C objects. The only times that it makes sense to mismatch interfaces is when you want a C object to reference a C++ object, or vice versa. Use the following approach to access C objects with the C++ Interface: • Include the C interface header file in the following manner: extern "C" { #include "omapi.h" }; // right way

If you include the C interface header file as:
#include "omapi.h" // wrong way

..your C++ compiler will think that the C/VERSANT functions in omapi.h should have a C++ linkage, which will result in linker errors for each C/VERSANT function referenced. Also, you should include cxxcls/pobject.h before omapi.h. • • • • • • • • For a link, use LinkAny or o_object instead of Link. For vstrs, use either Vstr or VstrAny. For link vstrs, use LinkVstrAny instead of LinkVstr. To retrieve objects from a database, use the C function o_locateobj() instead of the C++ dereference operators ->, type*, or PObject*. To acquire a write lock and mark an object for update, use o_preptochange() instead of the C++ PObject::dirty() method. To modify an attribute, acquire a write lock, and mark an object for update, use o_setattr() instead of a C++ method. To create a new C object, use o_createobj() rather than the C++ O_NEW_PERSISTENT() syntax. To access C++ objects with the C Interface, use o_locateobj(), o_setattr(), and o_getattr() in a normal manner to retrieve and access C++ objects.

If your C++ object uses simple inheritance, you can use casting to a struct pointer to access the fields.
159

VERSANT Database Fundamentals Manual

Objects deriving from PObject have one attribute of type PClass* that will show at the top of your objects. You cannot run the methods on an object created with the C Interface since the internal C++ pointers are not initialized properly. All C++/VERSANT collection classes may be used. You can use /VERSANT to access and manipulate all C++/VERSANT collection classes if you implement hash functions in both C++ and that operate in the two environments in the same way. In other words, for each member, your hash function must return the same hash value in both C++ and . This requirement requires care, because native C++ and hash functions work differently. You can compute an elemental hash value by sending #vElementalHash to an instance of Integer, Float, Double, Character, ByteString, or PObject. You can compute a combined hash value by using #vElementalCombinedHash:.. in the PVirtual class. With these hashing methods, you can develop a sharable persistent collection that involves hash look up. A sample program which allows a user to manage a VVSet collection can be found in the VERSANT filein/demos directory. You can browse a database using VMetaType class. You can browse through the class definitions in a database by sending the message #metaInfoFor: to the /VERSANT VMetaType class. You will receive a VMetaType instance that describes the corresponding database schema without your having to import the corresponding class. This is particularly useful if you need to view schemas defined from C++/VERSANT which are not intended for object sharing. You can store transient, runtime information. You can store transient, runtime information or relationships in attributes defined as having the #VSI_ST_NIL storage transform. Attribute names added by C++/VERSANT, such as __what and __vptr also have a #VSI_ST_NIL storage transform, but you should not use them to store runtime information, because future VERSANT releases may suppress these attributes when classes are imported into /VERSANT. If you want to use an attribute to store transient, runtime information, then create and reserve an attribute in the class when you define it in C++. There are some restrictions on queries over imported classes. You can perform queries over imported classes using the same /VERSANT methods that you would use
160

VERSANT Database Fundamentals Manual

for any other persistent class. However, there are some restrictions and differences in usage. When you import a class, the data types defined for the class in its database are often mapped to corresponding /VERSANT data types (see the following section for information on how types are mapped.) For example, • When you perform a path query, you must use the actual database attribute names and types known to the database rather than the variable names and types associated with the class as it appears in your Image. To get actual database names corresponding to an instance variable name, you can send the following message to the class with the instance variable: When you perform a normal query, you can use instance variable names as they appear in the class definitions in your Image. For normal queries, /VERSANT will do any necessary conversions between instance variable names and database schema attribute names. If you are querying on an elemental data type, because of possible variants in the way can map values (to SmallInteger or LargeInteger), you must prefix the value key with a type indicator in a pair of angle brackets.

#databaseAttributeNameFor:





For example, if you are querying on an age attribute in a Person class, and the age attribute has the database type o_u1b, then you must specify the query string as age=55 rather than age=55. The database types and their corresponding type indicators are: o_u1b o_u2b o_2b o_u4b o_4b

The default type indicator is . • If you are querying on a date or time attribute defined with the C++/VERSANT VDate or VTime classes, you must also provide a type indicator.

Database types and their corresponding type indicators are:
VTime VDate

161

VERSANT Database Fundamentals Manual

For example, for an embedded VTime attribute, all the following predicate strings are both valid and equivalent to one another:
"Use actual seconds of the VTime attribute." 'time = 811836204' "Use the Timestamp formatted string." 'time = ''9/22/95 11:04pm''' "Use term key substitution." | timestamp pred | timestamp := Timestamp readFrom: '9/22/95 11:04pm'. p := VPredicate from: 'time = :x'. p valuesAt: #(#x) put: (Array with: timestamp).

Storage Transform Concepts
When an object is read from a database into a Image, attribute values are converted to native objects. When an object in an Image is written to a database, these objects are converted back to values of their database domain type. Due to language differences, the mapping between a database data type and within a given range. type may be supported only

For example, suppose that a database contains a class with an attribute of data type o_u1b (a one-byte, unsigned integer). When an object of that class is read from a database, the data type o_u1b will be mapped to the class SmallInteger. When that object is written back to a database, VERSANT will attempt to convert the value of type SmallInteger back to type o_u1b. This can cause problems, because a SmallInteger can contain a larger value than o_u1b. Similarly, a Character can have value from 0 to the largest SmallInteger, while the corresponding database data type char can only assum the values between -128 and 127. In general, you must take responsibility for choosing the right C++ data type when creating classes whose instances will be used by both C++ and applications. The following table lists all the type mapping supported in the current /VERSANT interface. The first column of the table list the data type that you might be using in your C++/VERSANT application when define the persistent classes. The second column lists the data type that the corresponding first column would be converted to. The third column is the name of the class that the corresponding database data type would be mapped to. The fourth column gives the corresponding storage transform symbol. For basic elemental data types, the supported data range is also listed.

Storage Transforms for Elemental Data Types
C++
o_1b char

Database char char

Transform
#VSI_ST_CHAR #VSI_ST_CHAR

Allowable
0 to 127 0 to 127

162

VERSANT Database Fundamentals Manual

signed char o_bool o_u1b unsigned o_2b short signed o_u2b unsigned short o_4b int long signed int signed long o_u4b unsigned unsigned int unsigned long o_float float o_double double type* Link o_object

char o_u1b o_u1b o_u1b o_2b o_2b o_2b o_u2b o_u2b o_4b o_4b o_4b o_4b o_4b o_u4b o_u4b o_u4b o_u4b o_float o_float o_double o_double o_ptr Link o_object

#VSI_ST_CHAR #VSI_ST_U1B #VSI_ST_U1B #VSI_ST_U1B #VSI_ST_2B #VSI_ST_2B #VSI_ST_2B #VSI_ST_U2B #VSI_ST_U2B #VSI_ST_4B #VSI_ST_4B #VSI_ST_4B #VSI_ST_4B #VSI_ST_4B #VSI_ST_U4B #VSI_ST_U4B #VSI_ST_U4B #VSI_ST_U4B #VSI_ST_FLOAT #VSI_ST_FLOAT #VSI_ST_DOUBLE #VSI_ST_DOUBLE #VSI_ST_NIL #VSI_ST_OBJECT #VSI_ST_OBJECT

0 to 127 0 to 255 0 to 255 0 to 255 -32768 to +32767 -32768 to +32767 -32768 to +32767 0 to 65535 0 to 65535 -2147483648 to +2147483647 -2147483648 to +2147483647 -2147483648 to +2147483647 -2147483648 to +2147483647 -2147483648 to +2147483647 0 to +4294967295 0 to +4294967295 0 to +4294967295 0 to +4294967295 -10**38 to -+10**38, 6 digits of accuracy -10**38 to -+10**38, 6 digits of accuracy -10**307 to +10**307, 14 digits of accuracy -10**307 to +10**307, 14 digits of accuracy nil

163

VERSANT Database Fundamentals Manual

Storage Transforms for Special Embedded Types
C++
VDate VTime

Database
VDate VTime Date Timestamp

Transform
#VSI_ST_VDATE #VSI_ST_VTIME

VDate and VTime are C++/VERSANT classes used for attributes. When brought into , instantiated as instances of Date and Timestamp.

attributes are

These two embedded types are handled specially, because they are widely used in C++/VERSANT applications. Mapping these types to the Date and Timestamp class allows objects to share the behavior of the two existing classes. Also, it eliminates the need to duplicate the effort in providing methods for manipulating related attributes in each application specific imported class. Methods are available to do date and timestamp value conversion between Date to VDate and between
Timestamp and VTime.

Storage Transforms for Fixed Array Types
C++
o_1b[n] char[n] signed char[n] o_u1b[n] unsigned char[n] o_2b[n] short[n] signed short[n] o_u2b[n] unsigned short[n] o_4b[n] int[n] long[n] signed int[n] signed long[n] o_u4b[n] unsigned[n] unsigned int[n] unsigned long[n] 164

Database char[n] char[n] char[n] o_u1b[n] o_u1b[n] o_2b[n] o_2b[n] o_2b[n] o_u2b[n] o_u2b[n] o_4b[n] o_4b[n] o_4b[n] o_4b[n] o_4b[n] o_u4b[n] o_u4b[n] o_u4b[n] o_u4b[n]

Transform
#VSI_ST_CHAR_ARRAY #VSI_ST_CHAR_ARRAY #VSI_ST_CHAR_ARRAY #VSI_ST_U1B_ARRAY #VSI_ST_U1B_ARRAY #VSI_ST_2B_ARRAY #VSI_ST_2B_ARRAY #VSI_ST_2B_ARRAY #VSI_ST_U2B_ARRAY #VSI_ST_U2B_ARRAY #VSI_ST_4B_ARRAY #VSI_ST_4B_ARRAY #VSI_ST_4B_ARRAY #VSI_ST_4B_ARRAY #VSI_ST_4B_ARRAY #VSI_ST_U4B_ARRAY #VSI_ST_U4B_ARRAY #VSI_ST_U4B_ARRAY #VSI_ST_U4B_ARRAY

VERSANT Database Fundamentals Manual

o_float[n] float[n] o_double[n] double[n] type *[n] Link[n] o_object[n]

o_float[n] o_float[n] o_double[n] o_double[n] o_ptr[n] Link [n] o_object[n]

#VSI_ST_FLOAT_ARRAY #VSI_ST_FLOAT_ARRAY #VSI_ST_DOUBLE_ARRAY #VSI_ST_DOUBLE_ARRAY #VSI_ST_NIL_ARRAY #VSI_ST_OBJECT_ARRAY #VSI_ST_OBJECT_ARRAY

Storage Transforms for Vstr Types
C++
Vstr Vstr PString VString Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr

Database
Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr Vstr

Transform
#VSI_ST_CHAR_VSTR #VSI_ST_CHAR_VSTR #VSI_ST_CHAR_VSTR #VSI_ST_CHAR_VSTR #VSI_ST_U1B_VSTR #VSI_ST_U1B_VSTR #VSI_ST_2B_VSTR #VSI_ST_2B_VSTR #VSI_ST_2B_VSTR #VSI_ST_U2B_VSTR #VSI_ST_U2B_VSTR #VSI_ST_4B_VSTR #VSI_ST_4B_VSTR #VSI_ST_4B_VSTR #VSI_ST_4B_VSTR #VSI_ST_4B_VSTR #VSI_ST_U4B_VSTR #VSI_ST_U4B_VSTR #VSI_ST_U4B_VSTR #VSI_ST_U4B_VSTR #VSI_ST_FLOAT_VSTR #VSI_ST_FLOAT_VSTR

165

VERSANT Database Fundamentals Manual

Vstr Vstr LinkVstr

Vstr Vstr LinkVstr

#VSI_ST_DOUBLE_VSTR #VSI_ST_DOUBLE_VSTR #VSI_ST_OBJECT_VSTR

Object Sharing Methods
Following are methods useful when sharing objects.
ODBInterface importSchema: — Import a class definition. PObject fileInSourceFromDB: — Answer file-out source text. loadSourceFromDB: — Load file-out source. storeSourceToDB: — Store file-out source. vElementalHash — Answer an integer value that can be used as a hash index in a collection. PVirtual vElementalCombinedHash: — Answer a combined hash value. VMetaType allCXXDefinedSchemsFromDB: — Answer descriptions of all database classes. attributes — Answer descriptions of class attributes. metaInfoFor: — Answer a description of a database class. name — Answer the name of a database class. supers — Answer descriptions of super classes. VAttribute domain — Answer the database class name. name — Answer the attribute name. repeatFactor — Answer the attribute repeat factor. storageTransform — Answer the derived storage transformation symbol for the attribute. type — Answer the attribute type. ByteString vElementalHash — Answer a hash value for a ByteString object. 166

VERSANT Database Fundamentals Manual

Character vElementalHash — Answer a hash value for a Character object. Double vElementalHash — Answer a hash value for a Double object. Float vElementalHash — Answer a hash value for a Float object. Integer vElementalHash — Answer a hash value for an Integer object.

167

VERSANT Database Fundamentals Manual

Chapter 10: Optimistic Locking
Optimistic Locking Overview ......................................................................................................... 169 Optimistic Locking Actions ............................................................................................................ 171 Multiple read inconsistencies......................................................................................................... 178 Optimistic Locking Prototocol ........................................................................................................ 179 Optimistic Locking General Notes .................................................................................................. 184 Examples .................................................................................................................................... 186 Optimistic Locking, C++/VERSANT Example ............................................................................... 186

168

VERSANT Database Fundamentals Manual

Optimistic Locking Overview
Sometimes locking is too costly Standard VERSANT read, update, and write locks provide consistent and coherent access guarantees in a multiple user environment. These guarantees are necessary and appropriate under most circumstances. Sometimes, however, you may want to read a large number of objects but update only a few of them. Or, you may be in a situation where there is only a small chance that the objects you want to work with will be updated by others. In this situation, holding a lock on all objects you access can interfere with the work of others. Accordingly, VERSANT provides optimistic locking features that allow you to work with objects without holding locks. You do not have to use optimistic locking features to safely access and update unlocked objects, but the side effects of the alternative approaches might not be right for your situation. For example, you can safely checkout an object without a lock, update it, and then check it in. However, checking in an unlocked object will create a new object with a new logical object identifier, which may not be what you want. Or, you could version the object you want to access, which means that you will get immediate access, but that each change will create a new version, which only defers the issue of which version is the "correct" one. How to use optimistic locking features To use VERSANT optimistic locking features to work with unlocked objects, do the following. • • • Add a time stamp attribute to class definitions. Start an optimistic locking session. Follow an optimistic locking protocol. Following an optimistic locking protocol will ensure the coherence and consistency normally provided by locks. • Optionally use special methods. Optionally use performance related methods, which will allow fine-grain control over the objects you want to change. • Optionally use event notification. Optionally use event notification methods, which will let you know when objects held with optimistic locks are modified.
169

VERSANT Database Fundamentals Manual

By doing the above, you will get a shorter duration of locking, which will improve performance and improve concurrency of access among multiple users. At the same time, the time stamp validation at commit, delete, and group write time will still keep databases consistent.

170

VERSANT Database Fundamentals Manual

Optimistic Locking Actions
Add time stamp attribute To make a class "optimistic locking ready," add a time stamp attribute to the class definitions for the objects you will be accessing. If an object has a time stamp attribute, the VERSANT commit, delete, group write, and check time stamp methods will automatically use the time stamp to detect obsolete copies in the object cache and prevent you from using the obsolete copies as the basis for changing the database object. An obsolete copy will occur if, while you are working with an unlocked copy of an object, another user updates the original object in the database. If your object has a time stamp attribute, you will automatically be told if your commit, delete, and group write method will overwrite changes made by another user since you read your object. An obsolete copy will also occur if you try to modify an object that another user has already deleted. Time stamps are a convenience feature. You could avoid having obsolete copies by first refreshing every unlocked object you wanted to change before proceeding to a commit. However, this would be costly, both because of the necessary fetching of objects and because of the time required to make detailed evaluations of each attribute in each object. Once you add a time stamp attribute to an object, the time stamp attribute will be updated, no matter who does the updating and no matter the kind of session used. When an object with a time stamp attribute is created, its time stamp attribute is set to 0. Thereafter, each update written to a database will increment the attribute by 1 during the normal commit and group write process. You can rely on normal commit, group write, and delete methods to tell you if you have an obsolete copy, or you can detect obsolete copies in your object cache by using the "check time stamp" method before your commit. When you detect an obsolete copy by checking time stamps, what you do next is up to you. For example, you might want to refresh your copy of the object, inspect it, and then reapply some or all of your modifications. Or you may simply want to abandon your update. The procedures to add a time stamp attribute to a class is tightly bound to your interface language. C/VERSANT To define a time stamp attribute in a C class, add the following lines to your attribute descriptions:

171

VERSANT Database Fundamentals Manual

static o_attrdesc clsAttrs[] = { {TIMESTAMP_ATTR_NAME_STR,{"",""}, TIMESTAMP_ATTR_TYPE_STR, O_SINGLE, NULL, 0}, . . };

Then, before calling o_defineclass(), add the following lines to your class definition struct: typedef struct { O_TS_TIMESTAMP, . . } clsInstance;

C++/VERSANT To define a time stamp attribute in a C++ class, add the following lines to your class definitions: class SampleClass : public PObject { public: O_TS_TIMESTAMP; . . };

Begin optimistic locking session In other kinds of sessions, as soon as you mark an object dirty, VERSANT will attempt to acquire a write lock on that object. In an optimistic locking session, all implicit lock upgrades are suppressed. Suppression of implicit lock upgrades allows you to continue working with your objects, as long as you like, without setting and holding a lock, which is the point of using optimistic locking. Of course, a write lock will still automatically be set on dirty objects when you commit. An optimistic locking session will also suppress object swapping and provide automatic detection of obsolete copies. c c++ o_beginsession() with O_OPT_LK beginsession() with O_OPT_LK

Check time stamps Check time stamps to detect any obsolete copies in the object cache. You must be careful to check both the objects marked dirty and the objects inter-related to them. When
172

VERSANT Database Fundamentals Manual

you consider inter-related objects, you should consider both hierarchial relationships (such as subclass objects) and logical relationships. An example of a logical relationship is when, say, you want to change B only if A is greater than 10. In this case, you should check both B (the changed object) and A (the logically related object) in order to prevent changing B if the value of A has changed since you read it. c c++ o_checktimestamps() checktimestamps()

Downgrade short lock Release locks on specified objects without flushing objects from the object cache. c c++ o_downgradelocks() downgradelocks()

Delete objects Delete objects in a vstr or collection. This method enhances performance by deleting a group of objects with the least possible number of network messages. c c++ o_gdeleteobjs() gdeleteobjs()

Checkpoint commit short transaction with group Perform a checkpoint commit on objects in a vstr or collection and maintain objects in the object cache. c c++ o_xactwithvstr() xactwithvstr()

Commit and retain cache Rollback and retain cache Most commit and rollback routines allow you optionally to prevent flushing of the object cache. (Exceptions are the C++/VERSANT commit() and rollback() methods.) However, in an optimistic locking session, a better way to handle the object cache is to use commit and rollback routines that operate only on objects in a vstr or collection. However, if you use a group commit or rollback, you must be careful to place in the vstr or collection all objects marked dirty and all objects inter-related to them. When you consider inter-related objects, you should consider both hierarchial relationships (such as subclass objects) and logical relationships. An example of a logical relationship is when, say, you want to change B only if A is greater than 10.

173

VERSANT Database Fundamentals Manual

Commit and retain cache c c++ o_xact() xact()

Commit a group of objects c c++ o_xactwithvstr() xactwithvstr()

Rollback and retain cache c c++ o_xact() xact()

Rollback a group of objects c c++ o_xactwithvstr() xactwithvstr()

C/VERSANT and C++/VERSANT An option in o_xact() and xact() allow you to prevent flushing the entire object cache after a commit. This might be useful, but normally you would use the commit with vstr routine in an optimistic locking session. Drop read locks automatically When you fetch an object, many routines will place a read lock on the object. If you are using optimistic locking, you will want to drop the read lock on the fetched object as soon as possible. One way to drop a read lock is to track the objects fetched and then explicitly drop the lock with a routine such as the C/VERSANT o_downgradelock() function. If you know that you always want to downgrade read locks on fetched objects, you can specify automatic lock downgrading. This approach does not require you to keep track of fetched objects and reduces network calls. To automatically downgrade read locks, use a "set thread options" routine with the O_DROP_RLOCK option. Following is a description of the O_DROP_RLOCK option.
O_DROP_RLOCK

For this thread, drop read locks when objects are retrieved from a database. This option will have no impact on intention read locks set on the class objects corresponding to the instance objects retrieved. Read locks are held on instance objects during the duration of the read operation (which protects you from seeing uncommitted objects) and then dropped when the read operation is finished.
174

VERSANT Database Fundamentals Manual

If you want to always drop read locks after fetching objects, this option reduces network calls, because it causes locks to be dropped by the database server process. By comparison, dropping locks with a down grade lock routine requires a separate network message from the application process to the server process. This option may be used in a standard session or an optimistic locking session. Thread option routines C/VERSANT thread option functions o_setthreadoptions() — Set thread options. o_unsetthreadoptions() — Restore thread options to their defaults. o_getthreadoptions() — Get thread options.

C/VERSANT functions that are affected by O_DROP_RLOCK The following routines, when invoked by a thread for which O_DROP_RLOCK has been set, will drop read locks on fetched objects. o_locateobj() — Get object. A read lock will be dropped if the lockmode parameter is RLOCK or IRLOCK. o_pathselectcursor() — Find object with cursor. Read locks will be dropped if the instlock parameter is specified as RLOCK or IRLOCK and O_CURSOR_RELEASE_LOCK is not specified in the options parameter. If you toggle O_DROP_RLOCK in the middle of a

cursor select, the new option will take effect at the next retrieval of objects.

o_fetchcursor() — Get object with cursor created by o_pathselectcursor(). Read locks will be dropped if the instlock parameter in o_pathselectcursor() is specified as RLOCK or IRLOCK and O_CURSOR_RELEASE_LOCK is not specified in the options parameter. If you toggle O_DROP_RLOCK in the middle of a cursor fetch, the new option will take effect at the next retrieval of objects. o_greadobjs() — Get objects. Read locks are dropped if the lockmode parameter if RLOCK or IRLOCK. This behavior is the same as setting the options parameter to be O_DOWN_GRADE_LOCKS parameter, except that only read and intention read locks are

dropped. o_getclosure() — Get object closure. Read locks are dropped if the lockmode parameter is RLOCK or IRLOCK. o_refreshobj() — Refresh object. A read lock is dropped if the lockmode parameter is 175

VERSANT Database Fundamentals Manual

RLOCK or IRLOCK. o_refreshobjs() — Refresh objects. Read locks are dropped if the lockmode parameter is RLOCK or IRLOCK. o_getattr() — Get attribute value. Read locks are dropped if the default lock mode is RLOCK or IRLOCK. o_getattroffset() — Get attribute offset. Read locks are dropped if the default lock mode is RLOCK or IRLOCK.

C++/VERSANT thread option methods setthreadoptions() — Set thread options. The default is to not drop read locks when

objects are fetched. Different threads in the same session may have different settings for thread options. unsetthreadoptions() — Restore thread options to their defaults. getthreadoptions() — Get thread options.

C++/VERSANT methods that are affected by O_DROP_RLOCK The following routines, when invoked by a thread for which O_DROP_RLOCK has been set, will drop read locks on fetched objects. locateobj() — Get object. A read lock will be dropped if the lockmode parameter is RLOCK or IRLOCK. select() — Find object with cursor. Read locks will be dropped if the instlock parameter is specified as RLOCK or IRLOCK and O_CURSOR_RELEASE_LOCK is not specified in the options parameter. If you toggle O_DROP_RLOCK in the middle of a cursor select,

the new option will take effect at the next retrieval of objects. fetch() — Get object with cursor. Read locks will be dropped if the instlock parameter VCursor() is specified as RLOCK or IRLOCK and O_CURSOR_RELEASE_LOCK is not specified in the options parameter. If you toggle O_DROP_RLOCK in the middle of a cursor

fetch, the new option will take effect at the next retrieval of objects. greadobjs() — Get objects. Read locks are dropped if the lockmode parameter if RLOCK or IRLOCK. This behavior is the same as setting the options parameter to be O_DOWN_GRADE_LOCKS parameter, except that only read and intention read locks are

dropped. getclosure() — Get object closure. Read locks are dropped if the lockmode parameter

176

VERSANT Database Fundamentals Manual

is RLOCK or IRLOCK. refreshobj() — Refresh object. A read lock is dropped if the lockmode parameter is RLOCK or IRLOCK. refreshobjs() — Refresh objects. Read locks are dropped if the lockmode parameter is RLOCK or IRLOCK. get_attribute_value() — Get attribute value. Read locks are dropped if the default lock mode is RLOCK or IRLOCK. getattroffset() — Get attribute offset. Read locks are dropped if the default lock mode is RLOCK or IRLOCK.

177

VERSANT Database Fundamentals Manual

Multiple read inconsistencies
If you perform multiple reads in separate operations and have set the O_DROP_RLOCK option on, your objects may not be consistent, because operations may have been performed on your objects between your reads. If you are going to use the O_DROP_RLOCK option, you must be able to tolerate multiple read inconsistencies. Example of Multiple Read Inconsistency — the danger of using implicit read lock downgrade mechanisms. Object cache (what you see) Time 1 Time 2 Time 3 You read Object A with a read lock. You see Object A with state 1. Because automatic downgrading has been specified, your read lock is downgraded. Another session modifies Object A and Object B and commits the changes. You see Object A with state 1, but to the database it as state 2. You read Object B with a read lock. Server cache (what database sees) Object A: state 1, no lock Object B: state 1, no lock Object A: state 1, read lock Object B: state 1, no lock Object A: state 1, read lock Object B: state 1, no lock

Object A: state 2, write lock Object B: state 2, write lock Time 5 Object A: state 2, no lock Object B: state 2, no lock Time 6 Object A: state 2, no lock Object B: state 2, read lock Time 7 You see Object A with state 1 and Object A: state 2, no lock Object B with state 2. Object B: state 2, no lock What you see at Time 7 is inconsistent with both the initial and the current database states, because the objects were retrieved at different times and their read locks were dropped at different times.

Time 4

178

VERSANT Database Fundamentals Manual

Optimistic Locking Prototocol
In other kinds of sessions, locks ensure that your objects and databases are coherent and consistent, although you must set the right locks at the right time. In an optimistic locking session, you must take responsibility for coherence and consistence by following an optimistic locking protocol. In other kinds of sessions, locks ensure that your objects and databases are coherent and consistent, although you must set the right locks at the right time. In an optimistic locking session, you must take responsibility for coherence and consistence by following an optimistic locking protocol. Optimistic locking protocol assumes: • • The objects involved have time stamp attributes. You are working within an optimistic locking session.

When you use optimistic locking, you should observe the following protocol. 1. Start an optimistic locking database session. 2. Read objects with locks and pins. Fetch your objects from their databases with read locks and pins. The group of objects you bring into your object cache is called the "optimistic transaction set." Unless you change the default lock or override the default lock in a group read method, copying an object from a database will normally set a read lock and pin the object in your object cache. Read locks are necessary to ensure consistency among the objects in your optimistic transaction set. For example, if you did not fetch your objects with a read or stronger lock, a subclass object might be updated while you were fetching a superclass object, which would compromise consistency. Pins are necessary to avoid automatic flushing. Normally, if you run out of virtual memory for your cache, VERSANT will swap unpinned objects back to their databases at its own discretion. This could cause problems, because the next time you touched a swapped object, you would get a new copy which might not be consistent with the rest of your original optimistic transaction set. 3. Downgrade locks. Once you have a consistent group of objects, use a "downgrade locks" routine to drop locks without changing the pin status.
179

VERSANT Database Fundamentals Manual

Alternately, for a thread, you can set automatic lock downgrading on. 4. Browse and update. Using normal procedures, browse and update the optimistic transaction set. Because you are in an optimistic locking session, when you mark an object dirty, VERSANT will not set a write lock on the object. During this time, if you touch an object not fetched during the read phase, a read lock may be set by default. In C++ , this can happen, for example, by dereferencing an object outside the optimistic transaction set. During this stage, you can, if you want, set the default lock to a null lock, but it is better to avoid fetching additional objects to prevent introducing an object not consistent with the original set of objects. Per normal behavior, check in, check out, schema evolution, and versioning methods will continue to implicitly set write locks on class objects. If you call these methods in an optimistic locking session, these implicit locks will be held until your enclosing short or long transaction ends. For performance reasons, you will probably want to place all objects that you change into a vstr or collection. This will allow you to perform a commit, group write, or group delete only on the desired group of objects (as explained in a following step). If you place only the objects that you change into a vstr or collection (rather than all objects in the optimistic transaction set), be sure that you also place in the group all objects with inter-dependencies with the changed objects. Keeping inter-dependent objects together is important. For example, if you change an object, you will want to make sure that the time stamps for its associated objects are also checked, either at the time of a group commit or in an explicit time stamp checking step. 5. Check time stamps (preferred). Before proceeding to a commit, you should use the "check time stamp" routine to determine which of your changed objects have become obsolete. The check time stamp method will set the default lock on all objects checked, so if you do find objects that are obsolete, you may want to refresh your copy with the "refresh objects" routine. 6. Commit or rollback changes. At any time, you can save or roll back your updates with a transaction commit or rollback. You can either choose a method that will keep your objects in your cache, so that you can continue working with them, or choose a method that will flush objects to their databases. At commit time, VERSANT does the following:
a. 180

In the application process, VERSANT increments the time stamp (if it exists) of each dirty

VERSANT Database Fundamentals Manual

object by one.
b. c. d.

VERSANT sends dirty objects from the object cache to their source databases in batches. On each dirty object, VERSANT sets a write lock on its source object in its source database. For each dirty object, VERSANT compares the time stamp in the dirty object with the time stamp in the source object. If the time stamp of the dirty object is greater than the time stamp of the source object by one, VERSANT writes the dirty object to the database. If the time stamp of the dirty object is not greater than the time stamp of the source object by one, VERSANT does not write the dirty object to the database.

e.

Steps a, d, and the check made in ‘e’ constitutes a "time stamp validation sequence." If all objects pass the time stamp validation, then the commit succeeds. If one or more objects fail the time stamp validation, then the commit fails. At commit time, VERSANT will normally scan all objects in your object cache looking for those marked dirty and will flush your object cache at the end of the transaction. To improve performance, you can optionally use a method that will commit or rollback changes only to objects in a vstr or collection. This allows you to limit the scope of the objects to be locked during the commit and whose time stamps are to be compared. If your commit fails... If your commit fails, perhaps because some objects have outdated time stamps or have been deleted by another user, you can either rollback or refresh the failed objects and try again. Rolling back the transaction will restore the objects to their values before they were modified. Refreshing the failed objects will load the latest committed objects from the server. If you refresh the objects, you should use a read lock. The refreshed objects will be different from the timestamp failed objects or they will have been deleted (in which case, you will see an "object not found" error.) For example, suppose that you have two applications, Application_1 and Application_2, who are both working with the same two objects, ObjectA and ObjectB. Now, suppose the following sequence of events occurs. Action Application_1 Application_2

181

VERSANT Database Fundamentals Manual

Action Initial conditions

Application_1 ObjectA Timestamp = 0 Value = X ObjectB Timestamp = 0 Value = Y ObjectA Timestamp = 0 Value = X_1 ObjectB Timestamp = 0 Value = Y_1 ObjectA Timestamp = 0 Value = X_1 ObjectB Timestamp = 0 Value = Y_1 ObjectA Timestamp = 0 Value = X_1 ObjectB Timestamp = 0 Value = Y_1

Application_2 ObjectA timestamp = 0 value = X ObjectB timestamp = 0 value = Y ObjectA timestamp = 0 value = X_2 ObjectB timestamp = 0 value = Y ObjectA timestamp = 1 value = X_2 ObjectB timestamp = 0 value = Y ObjectA timestamp = 1 value = X_2 ObjectB timestamp = 0 value = Y

Both modify some objects

Application_2 commits and reads its results back

Application_1 tries to commit but fails due to timestamp of ObjectA

At this point, if Application_1 does a complete rollback, all objects would be flushed from the object cache. Alternately, Application_1 could perform a "rollback and retain." For C and C++, this means using the option O_ROLLBACK_AND_RETAIN with a transaction routine such as o_xact() or xact(). In this case, Application_1 will see the following:
ObjectA timestamp = 0 value = X_2 ObjectB timestamp = 0 value = Y

182

VERSANT Database Fundamentals Manual

If Application_1 refreshes each object, then Application_1 will see the following:
ObjectA timestamp = 1 value = X_2 ObjectB timestamp = 1 value = Y_1

In the above, note that the timestamps for dirty objects are incremented even though they fail timestamp validation. This is intended behavior and will only be experienced by the application whose commit fails because of timestamp failures.

183

VERSANT Database Fundamentals Manual

Optimistic Locking General Notes
Compatibility with strict locking schemes If you start any kind of session other than an optimistic locking or custom locking session, you will use "strict locking." Strict locking sessions use standard VERSANT locks to ensure database compatibility in a multi-user environment. All types of sessions use a two-phase commit protocol to ensure consistency among multiple databases. Optimistic locking sessions are compatible with strict locking sessions run by other users. Once you have defined a time stamp attribute, it will be updated by commits and group writes performed in any kind of session. Intra-session compatibility Intra-session -ses Check out, check in, schema evolution, and versioning methods implicitly set write locks on VERSANT system objects, regardless of the type of session. This means that if you use a check out, check in, schema evolution, or versioning method in an optimistic locking session, you will really be running with a mixture of optimistic and strict locking. This will cause no problems, as long as you stay aware of what is happening. Compatibility with savepoints Savepoints are not compatible with optimistic locking, because setting a savepoint flushes objects to their databases, which resets locks. Compatibility with nested transactions Optimistic locking cannot be used with nested transactions. Compatibility with C++/VERSANT links The C++/VERSANT link and link vstr classes automatically obtain locks on database objects when you first touch an object within a transaction. This may cause confusion when using optimistic locking. Delete behavior A delete operation is sent to a database immediately rather than at commit time. Query behavior If you use a query, remember that a query first flushes all dirty objects and marks them as clean before
184

VERSANT Database Fundamentals Manual

selecting objects. This means that if you update an object, perform a query, and then update the object again, you must mark the object dirty a second time to ensure that the second update is written to the database.

185

VERSANT Database Fundamentals Manual

Examples
Optimistic Locking, C++/VERSANT Example
The following C++/VERSANT example assumes that the Employee class has a time stamp attribute:
#include #include #include "person.h" #include "departme.h" class Employee : public Person { protected: // attributes Link department; o_u4b number; o_float salary; PString job_description; VDate last_raise; public: O_TS_TIMESTAMP; // constructor and destructor Employee( const PString& name, Department* department, o_u4b number, o_float salary, const PString& job_description); virtual ~Employee(); // accessors virtual Department& get_department() const; virtual o_u4b get_number() const; virtual o_float get_salary(); virtual PString get_job_description() const; // modifiers virtual void set_department(Department* department); virtual void set_number(o_u4b number); virtual void set_salary(o_float salary); virtual void set_job_description( const PString& job_description); // inherits key methods from Person };

186

VERSANT Database Fundamentals Manual

Following is an optimistic locking example program named opt_lock.cxx.
/* * opt_lock.cxx */ #include #include #include #include "employee.h" #include "departme.h" void usage(char** argv) { cout 20; \ select name, number from (1467.0.20484)->employees \ where number > 20; \ select name, number from (1467.0.20485); \ update Employee set name = 'Bill' where number = 100022; \ update Department set employees += 1467.0.20485; \ update (1467.0.20485) set name = 'Bill'; \ insert into Department (name) values ('Marketing');\ select name, number from Employee where number = $1; \ delete from Employee where number = 100023; \ delete (1467.0.20485); \ rollback; \ commit; \ quit "; /* Allocate space to hold the result */ o_parseresult *parse_result = (o_parseresult *) malloc(sizeof(o_parseresult)); if (!parse_result) { printf("Failed to allocate space for parse result.\n"); exit(-1); } if (argc != 2) { printf("Usage vqlsample \n"); o_exit(-1); } strcpy(dbname, argv[1]); /* Open database */ 511

VERSANT Database Fundamentals Manual

options[0]=0; if (o_beginsession("VQL_TRAN", dbname, "VQL_SESSION", options) != O_OK) { printf("Failed to open database %s\n", dbname); exit(-1); } /* Parse VQL Statements */ if (o_parsequery(querystring, parse_result, dbname) != O_OK) { printf("%s\n", querystring); printf("%s\n", 1+parse_result->prs_err.prer_tokenoffset, "^"); printf("%s\n", parse_result->prs_err.prer_errmsg); exit(-1); } num_statements = o_sizeofvstr(&parse_result->prs_pblkvstr) / sizeof(o_parseblock *); /* Processing each statement */ for (i = 0; i < num_statements; i++) { /* Get the handle of parse block. */ pblkp = ((o_parseblock **) parse_result->prs_pblkvstr)[i]; /* Substitute paramters if there is any */ if (pblkp->prb_paramvstr) { number = (o_4b *) malloc(sizeof(o_4b)); num_params = o_sizeofvstr(pblkp->prb_paramvstr) / sizeof(o_param); /* For this sample, there is only one parameter to ** substitute.*/ if (num_params != 1) { printf("Unexpected number of parameters. \n"); exit(-1); } param_pointer = ((o_param *) (*pblkp->prb_paramvstr)); /* Set the new value buffer */ *number = 100023; new_buffer.data = (o_u1b *) number; new_buffer.length = sizeof(o_4b); memcpy(¶m_pointer->prm_predterm->key, (o_bufdesc *) &new_buffer, sizeof(o_bufdesc)); } /* Retrieve objects which the operation will apply. */ switch (pblkp->prb_command) { /* Query a selection of objects */ case O_QRY_SELECT: 512

VERSANT Database Fundamentals Manual

case O_QRY_UPDATE: case O_QRY_DELETE: /* Apply query */ objectvstr = o_pathselect(pblkp->prb_classname, dbname, 0, NULL, pblkp->prb_options, IRLOCK, IRLOCK, pblkp->prb_predicate, pblkp->prb_vstrobj, pblkp->prb_vstrattr); if (objectvstr == (o_vstr) NULL) { if (o_errno != O_OK) { printf ("Query execution error %d\n",o_errno); exit(-1); } } break; /* Get the single object */ case O_QRY_SELOBJ: case O_QRY_UPDOBJ: case O_QRY_DELOBJ: /* Place the single object into objectvstr */ if (!o_newvstr(&objectvstr, sizeof(o_object), (o_u1b *) &pblkp->prb_vstrobj)) { printf("Fail to create vstr (err %d)\n", o_errno); o_exit(-1); } } /* Apply operation to the objects that have been retrieved */ switch (pblkp->prb_command) { case O_QRY_SELECT: case O_QRY_SELOBJ: /* Get the number of attributes */ num_attr = o_sizeofvstr(&pblkp->prb_prjvstr) / sizeof(o_projection *); /* ** For SELECT query of this operation, there is ** only two attributes: name, number; therefore ** we only expect two attributes */ if (num_attr != 2) { printf("Unexpected number of attributes. \n"); exit(-1); } 513

VERSANT Database Fundamentals Manual

/* Prepare the result buffer */ buffer.data = (o_u1b *) bufdata; buffer.length = 256; num_objs = o_sizeofvstr(&objectvstr) / sizeof(o_object); /* process each objects in objectvstr */ for (j=0; j < num_objs; j++) { char *attrname; object = ((o_object *) objectvstr)[j]; /* Get first attrbute: name */ attrname = (( (o_projection **) pblkp->prb_prjvstr)[0])->prj_attrname; if (o_getattr(object, attrname, &buffer) != O_OK) { printf("Error %d getting attribute.", o_errno); exit(-1); } printf("value of attribute name: %s \n", *((char **)buffer.data)); fflush(stdout); /* Get second attribute: number */ attrname = (((o_projection **) pblkp->prb_prjvstr) [1]) ->prj_attrname; if (o_getattr(object, attrname, &buffer) != O_OK) { printf("Error %d getting attribute.", o_errno); exit(-1); } printf("value of attribute number: %d \n \n", *((o_4b *)buffer.data)); fflush(stdout); } break; case O_QRY_INSERT: /* Execute insert statement could consists of two ** steps: ** 1. Create a new object ** 2. Assign values on attributes. This is the ** same operation as UPDATE. */ /* Step 1: Create a new object */ object = o_createobj ((char*)pblkp->prb_classname, NULL,FALSE); /* Step 2: Assign values on attributes using UPDATE */ /* 514

VERSANT Database Fundamentals Manual

** ** ** */ if {

Once the object is created, it is placed into result vstr and apply update on the attributes based on value given in VQL. (!o_newvstr(&objectvstr, sizeof(object), (o_u1b *)&object)) printf("doInsert(error): creating vstr \ (err %d)\n",o_errno);

} /* No "break" because values need to be assigned. */ case O_QRY_UPDATE: case O_QRY_UPDOBJ: /* update objects */ num_attr = o_sizeofvstr(&pblkp->prb_prjvstr) / sizeof(o_projection *); /* Get number of object to update */ num_objs = o_sizeofvstr(&objectvstr) / sizeof(o_object); for (j=0; j < num_objs; j++) { object = (((o_object *)objectvstr)[j]); for (k=0; k < num_attr; k++) { projection = ((o_projection **) pblkp->prb_prjvstr)[k]; switch (projection->prj_setcmd) { /* Assign operator */ case VQL_ASSIGN : /* Set new value to attribute */ if (o_setattr(object, projection->prj_attrname, &projection->prj_buf) != O_OK) { printf("Error: o_setattr failed (err %d)\n", o_errno); } break; /* ** Add new elements to a multi-values ** attributes. */ case VQL_APPEND: /* Prepare the result buffer */ buffer.data = (o_u1b *) bufdata; buffer.length = 256; /* Get the orginal collection */ if (o_getattr(object, projection->prj_attrname, &buffer) != O_OK) 515

VERSANT Database Fundamentals Manual

{ printf("Error: o_setattr \ failed (err %d)\n", o_errno); } /* Prepare the new value buffer */ new_buffer.data = (o_u1b *) new_bufdata; new_buffer.length = sizeof(o_vstr); /* Add new elements to collection.*/ vstr_pointer = (o_vstr *) new_buffer.data; (*vstr_pointer) = o_concatvstr((o_vstr *) (buffer.data), (o_vstr *) (projection->prj_buf.data)); /* Set new value to attribute */ if (o_setattr(object, projection->prj_attrname, &new_buffer) != O_OK) { printf("Error: o_setattr \ failed (err %d)\n", o_errno); } /* clean up */ o_deletevstr((o_vstr *)(buffer.data)); o_deletevstr((o_vstr *)(new_buffer.data)); break; } } } break; case O_QRY_DELETE: case O_QRY_DELOBJ: missing = (o_vstr) 0; /* delete objects */ if (o_gdeleteobjs(objectvstr, NULL, &missing) != O_OK) { printf("Delete fails. \n"); exit(-1); } break; case O_QRY_COMMIT: /* Commit transations */ o_xact(O_COMMIT, "VQL_TRAN"); break; case O_QRY_ROLLBACK: /* Rollback transcation */ o_xact(O_ROLLBACK, "VQL_TRAN"); 516

VERSANT Database Fundamentals Manual

break; case O_QRY_QUIT: quit = TRUE; break; default: printf("Unrecognized command."); exit(-1); } if (quit) break; } if (number) free(number); o_freequery(parse_result); o_endsession("VQL_SESSION", options); }

517

VERSANT Database Fundamentals Manual

Advanced Queries
This section explains in detail the concept of query enhancing capabilities of Versant ODBMS. To improve the query capability, a new concept of Virtual Attributes has been introduced. The enhanced query capability in Versant Release 6.0.0, will now allow you to query using Virtual Attributes and create index on Virtual Attributes.

Virtual Attribute
Virtual Attribute is a derived attribute, built on one or more normal attributes of a class. As the Virtual Attributes are computed at runtime, they are not part of the schema of a class, but can be indexed. The indexes on Virtual Attributes are maintained during normal operations like insert, delete and update and used during query processing. This release will support only b-tree index on Virtual Attribute of a Class. The implementation of Virtual Attribute Templates (the "class" of Virtual Attributes) are plugins provided as shared objects that gets loaded into the Versant server process’ address space.

Syntax of Virtual Attribute
A Virtual Attribute is used in certain operations where a normal attribute would be used. To indicate that it is virtual, it begins with a slash (/) character. Next follow parameters separated by spaces. Parameters that contain SPACE or TAB characters are quoted within curly braces({...}). This is important as parameters could be other Virtual Attribute with parameters. Following is the Virtual Attribute grammar that uses an informal BNF notation.

SLASH BRACE-START “{“ BRACE-END “}” virtual-attribute

“/”

::= SLASH { | BRACE-START

Similar Documents

Premium Essay

Database Administration

...relational databases in detail. Why do we mostly use relational databases in the industry? A relational database consists of a collection of tables in which each is assigned a unique name. The tables represent both data and the relationship among those data. In each table you find multiple columns and each column has a unique name. A relation is a two-dimensional table in which the following attributes, entries in a table are single-valued; each location contains a single value. Each column has its own distinct name and the values in each column must match the column name. The columns order is immaterial, and each row is distinct with the order of rows is immaterial. Relational databases are used today because of its simplicity, which eases the job of the programmer, compared to earlier data models such as network or the hierarchical model. A relational database can be seen as the data handling part of another application. The application instructs the database to perform searches, as well as add, delete and modify data via the Structured Query Language or SQL. The SQL standard is supported by all major database vendors, but the implementation of the full standard in all cases is not a guarantee. The common workhorse functions are the same in most cases. Databases change over time as information is inserted and deleted. The collection of information stored in the database at a particular moment is called an instance of the database. The overall design of the database is called...

Words: 398 - Pages: 2

Premium Essay

Database Administration

...DATABASE DESIGN AND THE IMPORTANCE OF DESIGNING A FUNCTIONAL PROCESS CIS475 Instructor: IBRAHIM ELHAG, PhD 3/6/2012 DATABASE DESIGN One of the most important if not the most important aspect of a database is the database design process. It is a must that the design is good and functional. A database consists of many different parts of an engineer’s design, which together makes up a complete database system. A database system is designed to manage large bodies of information. Database design is the construction of a database as a subsystem of an information system. Therefore, the database design process is an integral component of the information system design process. ( Chilson and Kudlac, 1983). One of the greatest problems in the application design process is the lack of foresight. During the design process there must be a thorough evaluation of your database, what it should hold, how data relates to each other, and most importantly, whether it is scalable. When it comes to the maintenance of your database it should be easy to maintain, this means storing as limited amount of repetitive data as possible. Let’s say you have a lot of duplicate data, and one instant of that data undergoes a name change, that change has to be made for all occurrences of that data. You can overcome this duplication problem by creating a table of possible values and use a key to refer to the value. That way, if the value changes names, the change occurs only...

Words: 2041 - Pages: 9

Premium Essay

Ray's Resume

...Team player demonstrating diagnostic, negotiating, and collaborative problem-solving skills • Strict adherence to established guidelines and policies • Ability to organize, prioritize, and coordinate multiple tasks • Sound working knowledge of Windows, MS Office, Lotus, Email/Internet and QuickBooks; typing speed of 50 words per minute and alpha-numeric data-entry speed of 7600 keystrokes per hour EMPLOYMENT HISTORY File Clerk/Administrative Assistant 1998-2010 Walter Barsamian, Attorney At Law Irvine, CA • Played key role in managing private law firm’s daily administrative office activities. • Efficiently processed and inputted thousands of files into legal database using Microsoft Excel Spreadsheets, organizing by client name. • Scanned Whole files into computer. These were scanned into Microsoft Excel Spreadsheets. These documents consisted of Medical Reports, Client Letters, Doctors Liens, Correspondence and letters to Judges. They were scanned using a scanning machine. • Answered phones and greeted clients, providing exemplary customer service. • Transcribed and created written correspondence using dictation and word processing applications; ensured accuracy of pleadings, correspondence and medical liens. • Managed copying, faxing, scanning, and distribution and filing of...

Words: 410 - Pages: 2

Premium Essay

Pursue a Master in Business Administration

...To pursue a master's in business administration Gary M. Newsome MGT/521 August 17, 2010 Stephanie Jackson To pursue a master's in business administration Many people set goals in life with a mindset of accomplishing these goals, and there is no more important goal than achieving a higher degree in education. It always has been my ultimate goal to achieve a master’s in business administration (MBA), but because of the time constraints and long deployments of military service, attending an institution of higher education for an MBA was out of the question. After 30 years of military service and beyond the age of 50, there is no better time to conquer my dreams and achieve my personal goal in obtaining my MBA. This accomplishment will open new a new path toward venturing into another outstanding career. The value of higher education is an important factor for advancement. The opportunity to excel would be the primary reason to achieve this goal while gaining the skills, and knowledge, of management. A position of increased responsibility requires much knowledge to be successful and a company, or business, may fail without these credentials. Mintzberg stated that “managers are important people who are supposed to sit above others, removed and disconnected from the work of making products and selling services. The higher they go, the more important they are, so that on reaching the top, becoming Chief Executive Officer; they are the corporation even if they arrived yesterday...

Words: 1190 - Pages: 5

Premium Essay

Business Reseach

...scheduling meeting and organizing office material, and accomplishment several other responsibilities. In this paper your foundation compensation strategy on administrative assistant job description, performance evaluation, external, and internal analysis. Administrative assistants obligate the responsibilities of functioning and retaining communications and report, secretarial and administrative tasks, business, planning, bureau business, research, gen management and guest services. These responsibilities are characteristic of an administrative assistant position; however the employment characteristically brings these tasks and other. The typical job duty of an administrative assistant is that you are need to have experience with computer, database, effect as well as general material on the internet and functioning with numerous styles of office knowledge. You should have the potency use different kinds of software, presentations to organize official documents, mail, and report as well as generate a proposal. However, contain scheduling and planning seminars or appointments, forming hard copy and electric documentation, accompanying research and organizations tasks (Henderson, 2006). The performance evaluation in the organization is that imitate the task duties of the Administrative Assistant. The efficient obligation in the performance evaluation of the...

Words: 515 - Pages: 3

Free Essay

Secretarial Career Essay

...community or vocational college. On a daily basis, secretaries will perform clerical duties and tasks relevant to the functioning of a company. More secretaries will be needed as the years progress. The minimum education required for a job as a secretary is a high school diploma. At the maximum, a degree of secretarial training would be required (“Secretary Job Description, Career as a Secretary” 2). To obtain secretarial training, a degree in office administration would have to be obtained. This degree can be acquired through a community college or a vocational school (“Secretaries and Administrative Assistants” 2). Two years of study are required for the office administration degree. The degree will demand a total of sixty-eight hours, which can be taken at seventeen hours per semester (“Office Administration”). It can be obtained at Faulkner State, a community college, for $1,904 per semester. $7,616 is the total cost for the degree (“Tuition”). There are no entrance requirements to attend Faulkner State for an office administration degree. The school has an “open door” admissions policy, which means that anyone can attend (“Admissions”). Special skills that are needed to have a career as a secretary include being able to manage time, being able to pay attention to details, and being able to plan and organize. Traits needed for this job would be the abilities of confidentially, reliability, and interpersonal communication skills. Being...

Words: 1260 - Pages: 6

Premium Essay

My Final C.V

...Yasser Omar Abdallah 28 Atef Abdel Latif Street, Mansoura, Egypt 31155 Yasser.abdallah10@gmail.com (002)0100-99 19 99 1 Personal Information: Full Name: Birth Date: Gender: Citizenship: Military Status: Marital Status: Yasser Omar Abdel Rady Abdallah. 25/07/1990. Male. Egyptian. Not called for Duty. Single. OBJECTIVE: Seeks the position of Business Administration teaching assistant position, these would help me enhance my best abilities while strengthening my weaknesses, Where my skills can be Developed and used effectively. Education B.S in Business Administration Business Administration Dep. Faculty of Commerce - English Section Mansoura University Mansoura, Dakahlya, Egypt. GPA: 86.2% Rank: First (in a class of 91 students). 2007-2011 Pre -Master of business administration 2011-2012 Faculty of Commerce – Business Administration Dep. Mansoura University Mansoura, Dakahlya, Egypt GPA: 78% Rank: First (in a class of 64 students). 1 MSc in Management of Technology School of management of Technology, Nile University Smart Village, Giza, Egypt 2013- present. Employment Vice President for Research and Development Issues Technology Transfer Office (TTO) Mansoura University Mansoura, Dakhleya, Egypt Job Responsibilities: July 2013- present 1. Full-delegated authority to act on behalf of the TTO's Director in his absence. 2. Responsible for the development and execution of the TTO's technical strategy. 3. Providing leadership and direction for the administrative...

Words: 779 - Pages: 4

Premium Essay

Dirt Bike #1

...Dirt Bikes USA was founded in the 1990’s by Carl Schmidt and Steven McFadden. Both experienced dirt bike riders, with engineering backgrounds, they saw a market for modern American made dirt bikes that were competitive with the foreign made cycles by capitalizing on their proximity to the racing circuit in the US. The company has been developing and manufacturing the best off-road, racing motorcycles possible. Noted for their own uniquely designed frames, more suited for off-road handling, they build their own bikes with genuine, quality custom parts & motors from around the world. Currently producing four models, appealing to serious trail and Enduro riders, they are working into the motocross market. Dirt Bikes USA has a very friendly, family atmosphere encouraging teamwork, attention to detail and quality, and continuous learning and innovation. This allows great communication within the company, and with suppliers and customers. Many of its employees are dirt bike racing enthusiasts, which creates a more personal sense of accomplishment to employees that will ultimately also use their products. Presently Dirt Bikes USA manufactures and sells four models of dirt bikes: the Enduro 250 (retail price $3250), the Enduro 550 (retail price $7600), the Moto 300 (retail price $4295), and the Moto 450 (retail price $8995). Product sales are made through a network of 40 distributors concentrated in the Western and Midwestern United States, with a small percentage sold in Europe...

Words: 516 - Pages: 3

Free Essay

Case Study 14.1- Supply Chain Management

...Case Questions 1. A decently overseen database may help the healing center accomplish its mission by the following points: * Cost of the each treatment in similar hospital is stored in the database to compare rate with other hospital. * Physicians can gather the relevant information quickly by providing the electronic medical record for each patient. * To find which programs and methods are best, create a historical record of the treatments. * Track the important measure to provide the data and information for example, normal length of patient wait, price for each day for a patient. 3. Hospital should carefully manage some of the cost and risk of using database because in a job market, there is short supply of skills such as database designer and database administrator. Without the specific faculty, it creates a risk to manage the database. The installation and administration expenses include updating software and installing of database and hardware. The translation cost includes the converting cost of older application into database environment. Instead of converting the hospital can choose new system. There is a need for the backup and recovery because the framework expenses are connected with those strategies. A hospital must predict the data administration cost and other activities cost related to data definition, ownership and maintenance. 6. Mountain View Hospital could use web based applications in a few ways. * Internet hospital personnel uses...

Words: 410 - Pages: 2

Free Essay

Distributed Systems

...Server Training (16 Courses) Training on how to build and manage SQL Server databases. Our SQL Server Training Courses provide the skills needed to build a solid foundation for SQL Server development. Introduction An overview of DBMS technology * How data is accessed, organized and stored * The database development process * Query and application development tools * CASE tools for database analysis and design * Tables, attributes and relationships * Primary and foreign keys * Relational integrity constraints * Manipulating data: selection, projection, join, union, intersection, difference * An integrated, active data dictionary * The query optimizer * Developing the logical data model * Mapping the data model to the relational model * Specifying integrity constraints * Defining the data in the data dictionary * Capturing entities, attributes and identifiers * Describing relationships: one-to-one, one-to-many, many-to-many * Optional and mandatory relationships * Resolving many-to-many relationships for implementation * Generating the SQL to build the database * Reverse engineering to capture the design of an existing database * SQL Programming Language Introduction 1 Days * Write SQL code based on ANSI/ISO standards to build Microsoft SQL Server or Oracle database structures * Update database content with SQL and transaction handling * Retrieve data with filter conditions and from...

Words: 1010 - Pages: 5

Premium Essay

Nt1330 Unit 1 Assignment 1

...United States 38 2. Figure 2 Shows the average salary for different DBMS jobs 39 Introduction Since decades, database management has had a prominent position in the field of IT. It mainly deals with the maintenance and operation of the databases of business services. Currently I have enrolled in master’s program in information assurance which is the combination of business assurance and information technology. It covers the core topics like networking, database management and security of systems for business organizations. I am strongly determined to work as a database administrator for an organization. A database is...

Words: 1799 - Pages: 8

Premium Essay

Happy

...M I C R O S O F T T E C H N O L O G Y A S S O C I AT E Student Study Guide EXAM 98-364 Database Administration Fundamentals Preparing for MTA Certification for Cert ca n Certification MICROSOFT TECHNOLOGY ASSOCIATE (MTA TECHNOLOGY ASSOCIATE (MTA) ECHNOLOGY C (MTA A) STUDENT STUDY GUIDE FOR DEVELOPERS UDY F DEVELOPERS 98-364 Database Administration Fundamentals Authors Peggy Fisher (Web Development and Database Administration). Peggy teaches computer science at a rural high school in central, Pennsylvania. Indian Valley High School offers courses in programming (C#, VB, and Java for the AP course), and Web design (Expression Web, HTML, JavaScript, and CSS). Peggy worked for a large insurance company outside Philadelphia, Pennsylvania, prior to leaving the corporate world to join the field of education. She has been at IVHS for the past eight years and truly enjoys her new career. Peggy also teaches part-time at Pennsylvania State University in the Continuing Education program. Her goal in teaching is to instill the love of learning so that her students will graduate and become lifelong learners. Peggy is the co-author of the Web Development Exam Review Kit in the MTA Exam Review Kit series. Patricia Phillips (Lead Author and Project Manager). Patricia taught computer science for 20 years in Janesville, Wisconsin. She served on Microsoft’s National K-12 Faculty Advisory Board and edited the Microsoft MainFunction website for technology teachers for two years...

Words: 11425 - Pages: 46

Free Essay

Ibm Db2

...IBM DB2 Express – C Introduction The intent of this paper is to describe the installation process of the Microsoft Windows version of the IBM DB2 Express-C database. This is a light-weight version of the more fully featured configuration of IBM’s best-selling DB2 database and includes core DB2 capabilities, free administration, development, autonomic, XML support and access to the online communities and forums. The version downloaded and running is configured for dual core processors and supports up to 2GB of system memory. Insights gained from working with the database after installed are also shared. Installation Process for DB2 Express-C Downloading and installing DB2 Express-C is easily accomplished over an Internet connection. The version installed is 389MB and took approximately 10 minutes to download over a cable modem running at fractional T1 speeds. Installation screens from the steps completed to get DB2 Express-C up and running are shown in the Appendix of this document. After installing the Control Center was invoked at the command line using the command db2cc which is specifically defined in the chapter assigned on DB2 Express-C. Using the command db2sampl -xml –sql to create the sample data worked, and there is the secondary option of using graphical interface commands to accomplish the same. The use of the DB2 Command Line tools show how quickly a multidimensional table can be viewed, edited and batch programming tasks completed using shell scripts...

Words: 728 - Pages: 3

Free Essay

Riordan Web Based Plan

...Riordan’s products and business systems, interviewed Riordan’s employees, and have determined the best course of action to implement the plan. Riordan Manufacturing is a plastics manufacturer based in several locations across the world. With three plants based in the continental US, which are located in Albany, Georgia; Pontiac Michigan; and in San Jose, California, which is the company headquarters. A fourth plant is located in Hangzhou, China will not be part of the plan as they purchase materials locally. This where we explain how the database will be set up. Refer to the ERD, Sequence diagram, Use Case diagram, and Class Diagram that followThe following paragraphs will describe the considerations that Riordan Manufacturing will need to make in implementing the database plan. Where ever it is possible to for our firm to do so, LTB and Associates will make a recommendation on the choice to make. In order to implement the database properly, these recommendations should be implemented in order to offer the tightest amount of security that will be possible. Type of Online ProcessingRiordan Manufacturing will need to decide between real-time asynchronous processing and batch processing. Real-time asynchronous processing is applicable when the processing must be performed immediately or when the results must eventually be communicated back to an on-line user. One of the problems with real-time processing is that real-time timers and events are required; they are expensive...

Words: 2477 - Pages: 10

Premium Essay

Information Systems and Software Paper

...Information Systems and Software Applications Paper Robert Morrison MIS/219 March 6, 2011 Martin Resnick Information Systems and Software Applications Paper This paper is about Information Systems and Software the company has chosen to enhance effectiveness of information systems, efficiency of departments, and gain an advantage related to information processing and management. The departments to be affected are the human resources, marketing, and management. The Reason for Information Systems and Software Information systems and software are the foundation for department and management to help employees perform tasks related to information processing and management. Information systems will help employees to deliver the correct information to the right people or department in the time designated, and in the correct format. (Samson, n.d). Software applications provide instructions for the hardware to function. Human Resources department (Quest webpage, 2011). Talent Platform Software by icIms’ has benefits of letting the employee service the application him or herself, salary and benefit data management, HR reports, and tools to help the user that are implement into the program, compatible with payroll systems. This system will reduce paper, and costs to the company by managing day to day operations of employees. This system will eliminate costly implementations and the need to train users on multiple systems. Marketing Department ...

Words: 579 - Pages: 3