Section 20.3. The Library

team bbl


20.3. The Library

The library we develop in this chapter will be similar to the ndbm library, but we'll add the concurrency control mechanisms to allow multiple processes to update the same database at the same time. We first describe the C interface to the database library, then in the next section describe the actual implementation.

When we open a database, we are returned a handle (an opaque pointer) representing the database. We'll pass this handle to the remaining database functions.

[View full width]

 #include "apue_db.h" DBHANDLE db_open(const char *pathname, int oflag,  ... /* int mode */); 

Returns: database handle if OK, NULL on error

 void db_close(DBHANDLE db); 


If db_open is successful, two files are created: pathname.idx is the index file, and pathname.dat is the data file. The oflag argument is used as the second argument to open (Section 3.3) to specify how the files are to be opened (read-only, readwrite, create file if it doesn't exist, etc.). The mode argument is used as the third argument to open (the file access permissions) if the database files are created.

When we're done with a database, we call db_close. It closes the index file and the data file and releases any memory that it allocated for internal buffers.

When we store a new record in the database, we have to specify the key for the record and the data associated with the key. If the database contained personnel records, the key could be the employee ID, and the data could be the employee's name, address, telephone number, date of hire, and the like. Our implementation requires that the key for each record be unique. (We can't have two employee records with the same employee ID, for example.)

[View full width]

 #include "apue_db.h" int db_store(DBHANDLE db, const char *key, const  char *data,              int flag); 

Returns: 0 if OK, nonzero on error (see following)


The key and data arguments are null-terminated character strings. The only restriction on these two strings is that neither can contain null bytes. They may contain, for example, newlines.

The flag argument can be DB_INSERT (to insert a new record), DB_REPLACE (to replace an existing record), or DB_STORE (to either insert or replace, whichever is appropriate). These three constants are defined in the apue_db.h header. If we specify either DB_INSERT or DB_STORE and the record does not exist, a new record is inserted. If we specify either DB_REPLACE or DB_STORE and the record already exists, the existing record is replaced with the new record. If we specify DB_REPLACE and the record doesn't exist, we set errno to ENOENT and return 1 without adding the new record. If we specify DB_INSERT and the record already exists, no record is inserted. In this case, the return value is 1 to distinguish this from a normal error return (1).

We can fetch any record from the database by specifying its key.

 #include "apue_db.h" char *db_fetch(DBHANDLE db, const char *key); 

Returns: pointer to data if OK, NULL if record not found


The return value is a pointer to the data that was stored with the key, if the record is found. We can also delete a record from the database by specifying its key.

 #include "apue_db.h" int db_delete(DBHANDLE db, const char *key); 

Returns: 0 if OK, 1 if record not found


In addition to fetching a record by specifying its key, we can go through the entire database, reading each record in turn. To do this, we first call db_rewind to rewind the database to the first record and then call db_nextrec in a loop to read each sequential record.

 #include "apue_db.h" void db_rewind(DBHANDLE db); char *db_nextrec(DBHANDLE db, char *key); 

Returns: pointer to data if OK, NULL on end of file


If key is a non-null pointer, db_nextrec returns the key by copying it to the memory starting at that location.

There is no order to the records returned by db_nextrec. All we're guaranteed is that we'll read each record in the database once. If we store three records with keys of A, B, and C, in that order, we have no idea in which order db_nextrec will return the three records. It might return B, then A, then C, or some other (apparently random) order. The actual order depends on the implementation of the database.

These seven functions provide the interface to the database library. We now describe the actual implementation that we have chosen.

    team bbl



    Advanced Programming in the UNIX Environment
    Advanced Programming in the UNIX Environment, Second Edition (Addison-Wesley Professional Computing Series)
    ISBN: 0321525949
    EAN: 2147483647
    Year: 2005
    Pages: 370

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net