# Persistent Base Class

Topics
Overview | Functions
Interface | Exceptions

Overview

The Persistent base class is an abstract class used to define the interface that makes an object persistent. A persistent object is an object that saves its state in-between program invocations. Normally an object's data, stored in memory, is lost when the program terminates. Persistent objects store their data both in memory and in a disk file. When the program is terminated and restarted again, the persistent object can restore its last state by loading its data from the disk file.

In order for the objects of a class to become persistent, the class must inherit the Persistent base class, and define the methods needed to store its objects to disk. The Persistent base class will use the methods defined in the derived class to maintain the data file and index file the database is connected to. The Persistent Object Database manager is used to manage pointers to the open data file and the open index file. Data files are used to store an object's data to disk. All data files are created by the VBD file manager and maintained by the Persistent base class. The index file is used to store the address where the object's data can be found in the data file. All index files are disk-based balanced multi-way trees created by the VBD file manger and maintained by the B-tree class.

The public member functions of the Persistent base class will become public member functions in the derived class. The protected member functions and data members will become private members of the derived class. Pure virtual functions are used to define the persistent object interface. The derived class must override the pure virtual functions and define its own procedures for reading, writing, deleting, and searching for its objects in the database. The derived class is also responsible for providing the Persistent base class with a unique class identification number and class name string. The class ID number will be used to identify the objects of the derived class in the database.

When the Persistent base class adds an object to the disk it allocates space in the data file for the variable block header, the object header, and the object data. The ObjectHeader struct is used to represent the object header. Object headers are stored directly after the variable block header.

    // (O)bject (H)eader (8 bytes total)
    struct ObjectHeader
    {
      INT32 ClassID;    // Class Identification number  (4 bytes)
      FAU ObjectID;     // Object Identification number (4 bytes)
    };

The object header stores the object class identification number and the data file address for this object. The object's address in the data file is used for an object identification number. Using the file address ensures that the identity of each object will be unique. This feature allows duplicate objects to be stored in the database. Space for the object is allocated starting at the address following the object header. The length of the object determines the number of bytes allocated. An object length is determined by a procedure defined in the derived class

The Persistent base class is designed to work with or without an index file. Index files are used to rapidly locate the objects in the data file using a B-tree algorithm. The B-tree nodes are fixed length entry keys that consist of a 64 byte string representing the object's name, a 32 bit integer representing the object's file address in the data file, and a 32 bit integer representing the class ID of the object. The entry keys are initialized and manipulated by the methods defined in the derived class. The Persistent base class provides the derived class with functions to add, remove, and find keys in the index file.

The Persistent base class provides the derived class with special functions for reading and writing character strings to data files. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself to the file. If the string is zero bytes in length, one byte will be allocated for the string and a null byte is written in place of the zero length string. When reading a string from the data file, the string length stored on disk is used to allocate a memory buffer for the string plus a null byte. The last byte of the memory buffer is null-terminated. NOTE: With the exception of a zero length string, a null byte is never written at the end of the string. A string must always be null-terminated in memory, unless it is being used to represent a pattern of raw bytes.

Methods for reading and writing user defined types, pointers, and references within an object must be defined in the class derived from the Persistent base class. The VBD class library provides its own platform independent data types to represent 16/32 bit signed and unsigned integers and 64 bit double precision floating point values. The persistent object database files will become platform dependent if built-in types such as short, int, long, float, or double are used within an object.

Functions

Persistent::Persistent(POD *DB)

- Class constructor responsible for connecting the Persistent base class to a POD manager object that represents the open data file and the open index file.

Exceptions:
CNoDatabaseOpen

Persistent::Persistent(const POD *DB)

- Class constructor responsible for connecting the Persistent base class to a POD manager object that represents the open data file and the open index file.

Exceptions:
CNoDatabaseOpen

Persistent::Persistent()

- Default constructor used for creating objects that are connected to an open database when initially constructed.

Persistent::Persistent(const Persistent &ob)

- Private class copy constructor used to disallow copying.

void Persistent::operator=(const Persistent &ob)

- Private class assignment operator used to disallow assignment,

void Persistent::WriteObjHeader(const ObjectHeader &oh, FAU addr)

- Protected member function used to write the object header to disk.

Exceptions:
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CAccessViolation
CFileReadError
CFileNotReady
CChecksumError

void Persistent::ReadObjHeader(ObjectHeader &oh, FAU addr)

- Protected member function used to read the object header from disk.

Exceptions:
CAccessViolation
CFileReadError
CFileNotReady
CFileSeekError

void Persistent::Connect(POD *DB)

- Protected member function used to connect the Persistent base class to a POD manager object that represents the open database.

Exceptions:
CNoDatabaseOpen

void Persistent::Connect(const POD *DB)

- Protected member function used to connect the Persistent base class to a POD manager object that represents the open database.

Exceptions:
CNoDatabaseOpen

unsigned Persistent::StringFileLength(const UString &s)

- Protected member function used to calculate the total number of bytes to be allocated for a user defined string in the data file. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself.

unsigned Persistent::StringFileLength(const char *s)

- Protected member function used to calculate the total number of bytes to be allocated for a null-terminated string in the data file. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself. If the string is zero bytes in length, one byte will be allocated for the string.

unsigned Persistent::StringFileLength(char *s)

- Protected member function used to calculate the total number of bytes to be allocated for a null-terminated string in the data file. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself. If the string is zero bytes in length, one byte will be allocated for the string.

void Persistent::WriteString(const UString &s, FAU addr)

- Protected member function used to write a user defined string to the data file at the specified file address. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself.

Exceptions:
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CAccessViolation
CFileReadError
CFileNotReady
CChecksumError

void Persistent::WriteString(const char *s, FAU addr)

- Protected member function used to write a null-terminated string to the data file at the specified file address. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself. If the string is zero bytes in length, one byte will be allocated for the string and a null byte is written in place of the zero length string.

Exceptions:
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CAccessViolation
CFileReadError
CFileNotReady
CChecksumError

void Persistent::WriteString(char *s, FAU addr)

- Protected member function used to write a null-terminated string to the data file at the specified file address. Strings are stored by writing the length of the string in a 32-bit integer value and then writing the string itself. If the string is zero bytes in length, one byte will be allocated for the string and a null byte is written in place of the zero length string.

Exceptions:
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CAccessViolation
CFileReadError
CFileNotReady
CChecksumError

void ReadString(UString &s, FAU addr)

- Protected member function used to read a user defined string from the open database at the specified file address.

Exceptions:
CAccessViolation
CFileReadError
CFileNotReady
CFileSeekError

char *Persistent::ReadString(FAU addr)

- Protected member function used to read a string from the open database at the specified file address. Returns a null-terminated string that represents the string stored on disk.

Exceptions:
CAccessViolation
CFileReadError
CFileNotReady
CFileSeekError

int Persistent::AddKey(EntryKey &key)

- Protected member function used to add an entry to the open index file. An entry key consists of three fields. A string name representing the object. The object address representing its location in the data file plus the object ID. And the class ID of the object representing the class that created it. Returns 1 if successful, -1 if duplicate key exists, or -2 if a file allocation error occurs.

Exceptions:
CCacheFull
CNullPtr
CDanglingPtr
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CAccessViolation
CFileReadError
CFileNotReady
CChecksumError

int Persistent::FindKey(EntryKey &key, int full_search = 0)

- Protected member function used to find an entry in the index file. An entry key consists of three fields. A string name representing the object. The object address representing its location in the data file plus the object ID. And the class ID of the object representing the class that created it. If full_search is true the key specified must match the object name, address, and class ID. By default the key specified will only be checked for a matching object name. Returns true if the key is found in the index file.

int Persistent::RemoveKey(EntryKey &key)

- Protected member function used to remove an index file entry from the open index file. An entry key consists of three fields. A string name representing the object. The object address representing its location in the data file plus the object ID. And the class ID of the object representing the class that created it. The key specified for removal is located in the index file by matching the object name, data file address, and class ID. Returns true if successful.

Exceptions:
CAssertError
CDanglingPtr
CSyncError
CAccessViolation
CFileReadError
CFileNotReady
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CChecksumError

FAU Persistent::AddObject(int find = 1) - Public member function used to add a new object to the database, based on the method defined in the derived class version of the Persistent::Write() function. By default this function will search the entire index file or data file for the object, based on the derived class version of the Persistent::Find() function, to determine if the object already exists before adding it. If find is false the object will be added without searching the database for duplicate entries. Returns the file address of the object added or zero if the object was not added to the database.

void Persistent::ReadObject(FAU addr)

- Public member function used to read an object from the database, based on the method defined in the derived class version of the Persistent::Read() function. The object will be read at the specified file address.

FAU Persistent::FindObject()

- Public member function used to check the existence of an object, based on the method defined in the derived class version of the Persistent::Find() function. Returns the file address of the object or zero if the object does not exist in the database.

FAU Persistent::ObjectAddress(int find = 1)

- Public member function used to obtain the file address of the object. By default this function will search the entire index file or data file for the object, based on the derived class version of the Persistent::Find() function, to locate the object and verify its file address. If find is false the object's address will be returned without verification.

void Persistent::DeleteObject(FAU addr)

- Public member function used to delete an object at the specified file address. This function will mark the object deleted and leave its data intact. If the free space in the VBD file is not reused, the object can be undeleted by marking the variable block normal.

Exceptions:
CSyncError
CAccessViolation
CFileReadError
CFileNotReady
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CChecksumError

void Persistent::RemoveObject(FAU addr)

- Public member function used to remove an object at the specified file address. This function will mark the object removed and destroy its data by setting all the bytes allocated for the object to zero.

Exceptions:
CSyncError
CAccessViolation
CFileReadError
CFileNotReady
CEOFError
CFileWriteError
CFileNotWriteable
CFileSeekError
CChecksumError

FAU Persistent::DeleteObject()

- Public member function used to delete an object based on the derived class version of the Persistent::Delete() function. Returns the address of the object deleted or zero if the object could not be deleted.

FAU Persistent::RemoveObject()

- Public member function used to remove an object based on the derived class version of the Persistent::Remove() function. Returns the address of the object removed or zero if the object could not be removed.

int Persistent::UsingIndex()

- Public member function that returns true if the POD manager is using an index file.

int Persistent::UsingIndex() const

- Public member function that returns true if the POD manager is using an index file.

int Persistent::RebuildIndex()

- Public member function that returns true if the POD manager was informed by the application that the index file and the data file are no longer in sync with each other. The index file will need to be rebuilt in accordance with the procedures defined in the derived class version of the Persistent::RebuildIndexFile() function.

int Persistent::RebuildIndex() const

- Public member function that returns true if the POD was informed by the by the application that the index file and the data file are no longer in sync with each other. The index file will need to be rebuilt in accordance with the procedures define in the derived class version of thePersistent::RebuildIndexFile() function.

Derived Class Interface

virtual INT32 Persistent::GetClassID() const

- Protected pure virtual function that must be defined in the derived class as a private member function. Returns a unique class identification number representing the class inheriting the Persistent base class. The ID number will be stored in the ObjectHeader and used to identify the object in the database as being an object of that class. NOTE: The Persistent base class does not use Run Time Type Information to identify the objects in the database. These features were removed do to portability issues between the various C++ compilers used to test the VBD class library.

virtual const char *Persistent:: GetClassName()

- Protected pure virtual function that must be defined in the derived class as a private member function. Returns a unique class name string representing the class inheriting the Persistent base class. The class name string is used to identify the object as being as an object of that class. NOTE: the Persistent base class does not use Run Time Type Information to identify the objects in the database. These features were removed do to portability issues between the various C++ compilers used to test the VBD class library.

virtual FAU Persistent::Write()

- Protected pure virtual function that must be defined in the derived class as a private member function. Defines the procedure used to write an object of the class inheriting the Persistent base class to disk.

virtual void Persistent::Read(FAU Address)

- Protected pure virtual function that must be defined in the derived class as a private member function. Defines the procedure used to read an object of the class inheriting the Persistent base class from disk at the file address specified.

virtual FAU Persistent::Find()

- Protected pure virtual function that must be defined in the derived class as a private member function. Used to find an object of the class inheriting the Persistent base class in the database.

virtual unsigned Persistent::ObjectLength()

- Protected pure virtual function that must be defined in the derived class as a private member function. Returns the file length of an object in the database.

virtual FAU Persistent::GetObjectAddress()

- Protected pure virtual function that must be defined in the derived class as a private member function. Returns the object address of an object in the database.

virtual void Persistent::SetObjectAddress(FAU addr)

- Protected pure virtual function that must be defined in the derived class. Used to set the object address of an object in the database to a specified file address.

virtual FAU Persistent::Delete()

- Protected pure virtual function that must be defined in the derived class as a private member function. Defines the procedure used to delete an object of the class inheriting the Persistent base class from disk. Must return the file address of the object deleted or zero if the object could not be deleted. The delete function is intended to mark the variable block deleted and preserve the data so that it can be undeleted if possible.

virtual FAU Persistent::Remove()

- Protected pure virtual function that must be defined in the derived class as a private member function. Defines the procedure used to remove an object of the class inheriting the Persistent base class from disk. Must return the file address of the object removed or zero if the object could not be removed. The remove function is intended to permanently remove the variable block from the file by destroying the object's data.

virtual int CompareIndex()

- Public virtual function that defines the procedure used to compare the index file entries to the data file entries. This function returns true if the data file and the index file entries are consistent with each other. Meaning that each object's address and class identification stored in the index file match the actual locations in the data file. NOTE: This function will always return false if it is not overridden in the derived class.

virtual int RebuildIndexFile(const char *fname)

- Public virtual function that defines the procedure used build a new index file named fname. Returns true if the index file was successfully rebuilt. NOTE: This function will always return false if it is not overridden in the derived class.

Exceptions

The Persistent base can generate any of the following exceptions if the CPP_EXCEPTIONS macro is defined in the EHandler class at compile time. NOTE: The appropriate try and catch statements within the application must handle these exceptions or the program will terminate. Derived classes that override any of the Persistent base class virtual functions must handle any file I/O exceptions in its version of that function. If the CPP_EXCEPTIONS macro is not defined, the global error hander will signal that an exception has occurred and will terminate the program as defined in the EHandler::Terminate() function.

CNoDatabaseOpen

- this exception is thrown if the derived class attempts to connect the Persistent base class to a database that is not open or does not exist.

CAssertError

- this exception is thrown if any assumptions made during program execution are evaluated and do not meet the conditions specified within the application, causing the entry not to be processed.

CDanglingPtr

- this exception is thrown if there are any dangling references to a reference counted pointer, indicating that a copy of this object is still being used by another object.

CAccessViolation

- this exception is thrown if an "end of file" error occurs during multiple file access. This exception was added to tell the application that the file has grown in size but the EOF marker has not.

CEOFError

- this exception is thrown if an "end of file" error is encountered.

CFileNotReady

- this exception is thrown if the file is not ready for reading.

CFileNotWriteable

- this exception is thrown if the file cannot be written to.

CFileReadError

- this exception is thrown if an error occurs while reading from the file.

CFileSeekError

- this exception is thrown if an error is encountered during a seek operation.

CFileWriteError

- this exception is thrown if the number of bytes written do not match the number of bytes requested to write.

CSyncError

- this exception is thrown if the block header's check word cannot be read. This indicates a file synchronization error, meaning the VBD file manager is not reading a valid variable data block or the block is corrupt.

CCacheFull

- this exception is thrown if all the cache buckets are locked, indicating that no more buckets can be acquired until another bucket is released.

CNullPtr

- this exception is thrown if an attempt is made to access a null file address or null memory location.

CChecksumError

- this exception is thrown if a bit error occurs when writing to disk. A 32-bit CRC checksum based on the Ethernet polynomial of 0x4C11DB7 is calculated when any data is written to the VBD file. The calculated checksum is then compared to data actually stored on disk. If the calculated checksum does not match the actual checksum, a bit error has occurred during data storage.

End Of Document