* PTool Interface for Version 2.3 *


 1. introduction 
 2. Ref class 
 3. Database class 
 4. new Operator 
 5. general Collection classes 
 6. Namespaces


1. Introduction

The first step to creating persistent objects is creating a
Database. A Database is a resource in which persistent objects
reside. A Database can be created on local disk, tape, or on remote
object servers.

We can declare a Database in the following fashion: 

        Database s( "filename" //The "Name" of the Database
                 , Mode // The mode of the Database( Read, ReadWrite )
                 , Place ); //Local disk, tape, client-server

Here are some example declarations: 

        Database s( "Photons" , Database::Read , Database::Remote );

A remotely-distrubted Database names photons that is in read-only mode. 

        Database p( "junk" , Database::ReadWrite );

A read-write Database names junk that is local disk (the default). 

Once we have our Database created, we need to declare persistent
reference to the objects we wish to be made persistent. This is done
using the template facility in C++:


     Ref< foo > Rfoo.

This declares a persistent reference to the object foo. Any object can
be made persistent, although particular implementations might require
extra care (this will be discussed in more detail later ).


Once the persistent reference has been declared, we can make it point
to a new persistent object like so:


        new( s ///This is the Database to allocate the object in
             , Rfoo ) //This is the reference
             foo( ... ); //This is the normal object initialization call

Now, we need to place these persistent objects in a place so that we
can access them the next time we execute our program. We need to place
them in a collection. All collection have the method insert_element(
reference ). And they can be used to make new iterators with which to
look at their contents. This is done in the following fashion:
 

   Collection c;
   c.insert_element( reference_to_something );
   [......]
   Iterator i( c.create_iterator() );

New persistent references can be gotten from the iterator until it
returns a false (boolean). It can be reset to the start of the
collection as well. This is done in the following fashion:


    Iterator i( c.create_iterator() );
    while( i.next( The_Ref ) != flase )
       {


       }
    i.reset();

Here are sample programs showing this: 

pop()
{
    Database s( "Crowley" ); // Using both defaults: R/W and local disk
    Ref< Weirdo > pal; // Making a reference to a Weird person
    for( int a = 0 ; a < 100 ; ++ a )
    {
        new( s , pal ) Demon( "me" , 42 );
        a.insert_element( pal ); //A Database is a collection too!
    }
}

acc()
{
    Database s( "Crowley" , Database::Read );
    Ref< Weirdo > pal; 
    Iterator i( s->create_iterator() ); // An iterator belonging to the collection
    while( i.next( pal ) != false )
    {
        pal->Spas(); // do odd things
    }
}



2. The Ref template

A Ref( persistent pointer ) is created by using a templated class
descriptor. A Ref instance is, in fact, an instance of this templated
Ref class.

The declaration syntax is a follows: 

    Ref< Foo > rFoo;

In this example: 

   "Foo" is the type of object the Ref will refer to. 

   "rFoo" is a variable that refers to a persistent object of type foo. 

The operators 

 == != 

are overloaded for use on Refs. 

   There also exist locked refs.  You can construct a LockedRef from an
ordinary ref of the same type.  A locked ref guarantees that the object that
it points to will stay in main storage while the locked ref exists.  
This allows quick access and even allows you to convert the locked ref 
into a real pointer and use it while the locked ref exists.

3. The Database class

A persistent object resides in the virtual space that is defined by a
Database. A persistent object is created in the space of a given
database, and the attributes of the database are inherited by the
persistent object (scope, location, etc ).
 

A database is declared in the following fashion: 

  Database s( name , Database::Mode , Database::Method );

Where: 

   "s" is the local variable which represents that database. 

   "name" is a character string representing the name to which the database 
   has been bound. 

   "Mode" is the access mode that the database is to be accessed in. Valid 
   modes are Read and ReadWrite. 

   "Method" is the method by which the persistent objects are stored. 
   They can be either placed on local disk with the Local setting, or 
   distributed across object servers with the Remote setting. 

A database can also be declared in the following fashion: 

    Database s;

Such an instance must be bound to a physical database before it can be
used. This can be done with the Open()method, which exactly mimics the
syntax of the constructor.  There is a corresponding Close() method
which take no arguments, and disassociates a Database object with a
physical Database. 

The database also acts as a collection for Refs, so that persistent
objects created in a given program run can be accessed by other,
future programs. It (the Database collection methods) follow exactly
the general syntax for collection classes.
 



4. The new operator.

PTool makes use of an overloaded new operator in order to create new
persistent objects. The syntax for creating new persistent objects is
as follows:
 

  new ( st , rFoo ) Foo(..);

Where: 

   "st" is the database in which the persistent object is to be created. 

   "rFoo" is a Ref to objects of type Foo which will point to the newly 
   created object after the completion of the new operation. 

   "Foo" is the normal constructor call for objects of type Foo such as 
   is normally done when invoking the new operator. 



5. The general form of collection classes and iterators

A collection class is an object into which persistent pointers to
objects can be placed.  Later, an iterator can be spawned that will
allow the programmer to examine the objects in the collection. The
general form for the collection class is is follows:
 

class Collection
{
    void insert_element( Ref );
    int cardinality();
    Iterator create_iterator();
};

Where: 

   "insert_element" adds a persistent pointer to said collection. 

   "cardinality" returns the number of objects in the collection. 

   "create_iterator" Returns a new iterator that can be used to examine 
   the objects in the collection 

Specific collection classes may have many more methods, but they will,
as a rule, follow this form.


The Iterator class is as follows: 


class Iterator
{
    void reset();
    bool next( Ref & );
};


Where: 

   "reset" moves the iterator back to the start of the collection. This is
   automatically done when the Iterator is first constructed. 

   "next" causes the Ref passed to it to refer to the next persistent 
   object in the collection. It returns true if it was able to get a 
   new pointer, and false if it could not get the next Persistent 
   object (if it reached the end of the collection).

This may seem a bit confusing, but this following code sample will
clarify matters:
 


Database s( "database-o-foos" ); //A database is a kind of collection too!
Iterator it( s.create_iterator() ); //Create an iterator for the Database
Ref< Foo > f;
while( it.next( f ) != false )
    f->FooMethod();


6. 

	If we are building many distributes stores, we will eventually
choose the same store name as another person using ptool.  This can
cause problems.  To fix this, namespaces can be used.  A namespace can
be created in the following way:

Database::Namespace( "title" );

	Where a good choice for "title" would be your name, or the name
of the project that you're working on.  This name will be prepended
to all of your folio files, so as to provide an extra level of safety 
in preventing store collisions.