Scanning Directories in a Shore Application
Version 0.1
The Shore Project Group
Computer Sciences Department
UW-Madison
Madison, WI
The DirScan class provides a convenient interface for scanning
directories. This document describes how to use the DirScan class. The
Shore release includes a simple example program called shls (``Shore
ls''), that illustrates the use of the DirScan class. Shls can be
found in the examples/shls directory of the Shore release.
An application scans a directory by creating a DirScan object. DirScan
objects are transient C++ objects, not persistent Shore objects. A DirScan
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.
Directory scans request blocks of directory entries from the Shore server
and store them in a buffer. Applications can set the size of this buffer,
although the size must be at least DEF_DIRSCAN_BUFSIZE to ensure
that the buffer is large enough to hold at least one directory entry. If a
smaller buffer size is requested, it will be rounded up to the default
size.
A scan of a directory returns some number of DirEntry structures.
The DirEntry type (defined in OCTypes.h) looks like this:
struct DirEntry
{
LOID loid;
int namelen;
char name[MAXNAMLEN + 1];
};
The fields of the structure are:
- namelen
- The length of the name field.
- name
- The null-terminated name of the entry. This name is
only the portion of the pathname stored in the directory; it is not a
complete pathname.
- loid
- The logical OID associated with the directory entry.
The public portion of the DirScan class is defined as follows:
class DirScan
{
public:
DirScan();
DirScan(const char *path, int bufsize = DEF_DIRSCAN_BUFSIZE);
shrc open(const char *path, int bufsize = DEF_DIRSCAN_BUFSIZE);
shrc next(DirEntry *entry);
~DirScan();
shrc close();
bool is_open();
shrc rc();
int operator==(shrc &rc);
int operator!=(shrc &rc);
};
Here, we describe each of the methods of DirScan:
- bool DirScan::is_open();
-
This method indicates whether the scan is open or closed.
- shrc DirScan::rc();
-
DirScan::rc returns the return code generated by the last operation
on the scan object.
- int DirScan::operator==(shrc rc);
-
- int DirScan::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) ....
- DirScan::DirScan()
-
This method is the default constructor for DirScan. It constructs a
closed scan. A scan can be opened on the object by calling open,
below.
- DirScan::DirScan(const char *path, int bufsize);
-
This constructor attempts to construct an open scan object. The path
argument should indicate a valid directory in the Shore filesystem, on
which the current transaction has at least read permission. The bufsize argument indicates the size of the scan's buffer. This parameter
defaults to DEF_DIRSCAN_BUFSIZE, which is large enough to hold at
least one directory entry. When using this constructor, 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 DirScan::open(const char *path, int bufsize);
-
This method opens a closed scan object. As with the above constructor,
path should indicate a valid directory on which the transaction has
at least read permission, and bufsize indicates the size of the
scan's buffer. Upon successful completion, RCOK is returned. Any
other return value indicates an error condition.
- shrc DirScan::next(DirEntry *entry);
-
The method returns the next directory entry in the scan. (See the above
description of the DirScan type.) If the next entry in the scan was
successfully retrieved, then RCOK is returned. If an attempt is made to
advance the scan past the end of the scan (i.e., next is called after
the last item in the scan has already been returned), the the return code
will be OC_EndOfScan. Any other return code indicates an error
condition.
- shrc DirScan::close()
-
Closes the scan object. Closing a scan object releases any resources
associated with the scan in both the server and client processes (such as
the scan buffer). 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 DirScan object is
destroyed (either via operator delete or when the DirScan object goes out
of scope), or when the transaction in which the scan was opened terminates.
- DirScan::~DirScan()
-
The DirScan destructor closes the scan object if it is open.
The following function prints the name and loid of each entry in the
directory given by the pathname argument.
int count(const char *pathname)
{
DirEntry entry;
int count = 0;
// Open a scan over the pool given by "pathname."
DirScan scan(pathname);
// Make sure the scan was successfully opened.
if(scan != RCOK){
cout << "Error scanning directory " << pathname << ": "
<< rc << endl;
return 0;
}
// Scan until end-of-scan or an error is encountered.
for(count = 0; scan.next(&entry) == RCOK; ++count);
cout << path << " has " << count << " objects." << endl;
// Check for errors.
if(scan.rc().err_num() != OC_EndOfScan){
cout << "Error scanning directory " << pathname << ": "
<< rc << endl;
return 0;
}
// The destructor will close the scan object.
return count;
}