Scanning Pools in a Shore Application
Version 0.1

The Shore Project Group
Computer Sciences Department
UW-Madison
Madison, WI

1 Introduction

The PoolScan class provides a convenient interface for scanning through the objects in a pool. This document describes how to use PoolScans, as well as known bugs and limitations of the PoolScan class. The Shore release includes three example programs that illustrate pool scans. The examples can be found in the examples/pscan directory of the Shore release.

2 The PoolScan Class

Applications scan pools by creating a PoolScan object. PoolScan objects are transient C++ objects, not persistent Shore objects. A PoolScan object can be in one of two states: open or closed. A scan must be opened inside a transaction, and can only be used inside the transaction in which it was opened. Once a scan is opened, it stays open until it is explicitly closed, or until the scan object is destroyed or the transaction terminates. This means, for example, that the scan object remains open even after the end of the scan has been reached, or if an error condition has been encountered.

The public portion of the PoolScan class is defined as follows:


    class PoolScan
    {
     public:

        PoolScan();
        PoolScan(const char *path);
        PoolScan(const REF(Pool) pool);

        shrc open(const char *path);
        shrc open(const REF(Pool) pool);

        shrc next(REF(any) &ref, bool fetch = false, LockMode lm = SH);

        ~PoolScan();
        shrc close();

        bool is_open();
        shrc rc();
        int operator==(shrc rc);
        int operator!=(shrc rc);
    };

Here, we describe each of the methods of PoolScan:

bool PoolScan::is_open();

This method indicates whether the scan is open or closed.

shrc PoolScan::rc();

PoolScan::rc returns the return code generated by the last operation on the scan object.

int PoolScan::operator==(shrc rc);
int PoolScan::operator!=(shrc rc);

These operators provide a convenient way to check the status of the scan. For example, applications can say: if(scan == RCOK) ... or if (scan != RCOK) ....

PoolScan::PoolScan()

This method is the default constructor for PoolScan. It constructs a closed scan. A scan can be opened on the object by calling one of the forms of open, below.

PoolScan::PoolScan(const char *path);
PoolScan::PoolScan(const REF(Pool) pool);

These constructors attempt to construct open scan objects. The path or pool argument should indicate a valid pool on which the transaction has at least read permission. When using these constructors, the application should check to make sure that the scan was successfully opened before attempting to use the scan. The is_open method (above) will return true if the scan was successful, false otherwise. Alternately, the rc method can be used for this purpose. It will return RCOK if the scan was successfully open. Any other return value indicates that a scan was not opened.

shrc PoolScan::open(const char *path);
shrc PoolScan::open(const REF(Pool) pool);

These methods open a closed scan object. As with the constructors above, path or pool should indicate a valid pool on which the transaction has at least read permission. Upon successful completion, RCOK is returned. Any other return value indicates an error condition.

shrc PoolScan::next(REF(any) &ref, bool fetch = false, LockMode lm = SH);

This method returns a ref to the next object in the scan (if the scan has just been opened, then it returns the first object in the scan). If true is passed for fetch, then the object will be fetched into the object cache, and a lock will be obtained on the object in the mode indicated by lm, if such a lock is not already held by the transaction. If false is passed for fetch then lm is ignored. By default, the object is not fetched.

The return value of next is RCOK if there was a next object in the scan. If an attempt is made to go beyond the end of the scan (i.e., a call to next is made after the last object in the scan has already been returned), then the return code will be OC_EndOfScan. Any other return code indicates an error condition.

shrc PoolScan::close()

Closes the scan object. Closing a scan object releases any resources associated with the scan in both the client and server processes. It also allows the scan object to be reused. Ordinarily, a scan object does not get closed implicitly. This means that applications must call this method to close a scan, even if the end of the scan has been reached or an error condition has been encountered. However, a scan will be closed implicitly when the PoolScan object is destroyed (either via operator delete or when the PoolScan object goes out of scope), or when the transaction in which the scan was opened terminates.

PoolScan::~PoolScan()

The PoolScan destructor closes the scan object if it is open.

3 A Pool Scan Example

The following function counts the total number of objects in the indicated pool.


    int count(const char *pathname)
    {
        REF(any) ref;
        int count;

        // Open a scan over the pool given by `pathname.'
        PoolScan scan(pathname);

        // Make sure the scan was successfully opened.
        if(scan != RCOK){
            cout << "Error scanning pool " << pathname << ": "
                 << rc << endl;
            return 0;
        }

        // Scan until end-of-scan or an error is encountered.
        for(count = 0; scan.next(ref) == RCOK; ++count);

        // Check for errors
        if(scan.rc().err_num() != OC_EndOfScan){
            cout << "Error scanning pool " << pathname << ": "
                 << rc << endl;
            return 0;
        }

        cout << path << " has " << count << " objects." << endl;

        // The destructor will close the scan object.

        return count;
    }

4 Bugs and Limitations

In the current release of Shore, an application can have only one scan open at a time, although any number of scans can be open over the course of a single transaction.

In the current release of Shore, an application scanning a pool will not see any objects that it has created inside the pool during the current transaction. Therefore, new object creation and pool scans should be performed in separate transactions.


zwilling@caseus.cs.wisc.edu
Thu Nov 3 14:19:16 CST 1994