=pod

=head1 NAME

C<DBM::DBass> - DBM with associative arrays, file locking and XML records

=head1 SYNOPSIS

    use DBM::DBass;

    die unless DBM::DBass::gestalt (-api => 'neo');
    my $db = DBM::DBass->new (
        -api  => 'neo',
        -file => '+<file.dbm',
        -lock => 'file.lock',
        -mode => 0644
    );

=head1 DESCRIPTION

This module provides methods to read, write and delete associative arrays in
DBM files, with file locking and XML records.

It uses a named argument C<-api> for class methods C<new> and C<gestalt> to
try to prevent later versions of the module from breaking preexisting APIs.

=head1 METHODS

=over 4

=item C<gestalt>

This method checks for the existence of an API:

    die 'no API neo' unless DBM::DBass::gestalt (-api => 'neo');

C<-api> is the calling API to check for.  One should use this method only for
development or testing, and not in frequently used applications.

=item C<new>

This method creates a new DBass object, and should be the first one called:

    my $db = DBM::DBass->new (
        '-api'  => 'neo',
        '-file' => '+<file.dbm',
        '-lock' => 'file.lock',
        '-mode' => 0644
    );

C<-api> is the calling API to use.  C<-file> is the read/write mode (default
is read-only) and DBM filename.  C<-lock> is the lock filename.  C<-mode> is
the file permissions mode of the DBM file.

If the DBM file is opened for read-only access, the lock file must preexist,
but can be empty.  In MacOS, one can create an empty file with SimpleText.  In
*nix, one can create an empty file with C<touch>:

    touch file.lock

This version of the module has APIs C<xeen> and X<neo>.  The C<xeen> API is
deprecated and provided for backward compatibility only, and the C<neo> API
should be used when possible.

=item C<close>

This method releases various resources in the DBass object, to allow other
processes to access the DBM file:

    $db->close;

Normally this method should not be used, as it renders the object useless for
the remainder of the program execution (and is automatically called when the
object is destroyed).

=item C<delete>

This method deletes records from the DBM file:

    $db->delete ('-keys' => \@keys);
    $db->delete ('-keys' => \%keys);
    $db->delete ('-keys' =>  $key );

B<Be careful.>  It can also delete all records:

    $db->delete;

=item C<keys>

This method returns record keys:

    my @keys = $db->keys;

=item C<read>

This method returns a hash reference pointing to records in the DBM file:

    my $smallerhashref = $db->read ('-keys' => \@keys, '-root' => $root);
    my $smallerhashref = $db->read ('-keys' => \%keys, '-root' => $root);
    my $smallhashref   = $db->read ('-keys' =>  $keys, '-root' => $root);
    my $entirehashref  = $db->read ('-root' =>  $root);

C<-keys> are the keys to match against.  C<-root> is the XML root tag name
used in storing the records.

=item C<write>

This method writes key-value pairs to the DBM file:

    $db->write (-hash => \%hash, -root => $root);

C<-hash> is the hash reference pointing to the key-value pairs (records).
C<-root> is the XML root tag name to use in storing the records.

=back

=head1 KNOWN ISSUES

The C<xeen> API is deprecated and provided for backward compatibility only,
and the C<neo> API should be used when possible.  The main reason for the API
name change is that the C<neo> record format is significantly different from
that of C<xeen>.

On platforms other than MacOS, *nix or Windows NT, C<flock> will probably
cause the module to crash and burn.

The module should be pronounced C</di'bas/>.

The C<xeen> API is not named after the IBM alphaWorks C<Xeena> XML editor.

=head1 CHANGES

    0.54  2000.01.19  renamed package to DBM::DBass, as per Tim Bunce

    0.53  2000.01.11  fixed Makefile.PL (oops!)

    0.52  1999.10.30  added check for _OBJ
                      added check for _HASHREF
                      fixed neo_read handling of _UNTAGGED
                      fixed neo_read to check for _HASHREF
                      fixed neo_write to check for _OBJ
                      fixed xeen_delete to check for _OBJ
                      fixed xeen_destroy to check for _OBJ
                      fixed xeen_new die preparation
                      fixed xeen_new to include _UNTAGGED
                      fixed xeen_read handling of _UNTAGGED
                      fixed xeen_read to check for _HASHREF
                      fixed xeen_write to check for _OBJ

    0.51  1999.10.26  fixed gestalt for wantarray
                      fixed neo_read to accept hash references as -keys
                      fixed xeen_delete to accept hash references as -keys
                      fixed xeen_read to accept hash references as -keys

    0.50  1999.10.06  added neo API (valid XML tags and lists of lists)

    0.40  1999.09.20  fixed DBM file locking bug in xeen_destroy
                      fixed DBM file locking bug in xeen_new
                      fixed xeen_delete to accept scalars as -keys
                      fixed xeen_read to accept scalars as -keys

=head1 AUTHOR

Copyright 1999, 2000 Nguon Hao Ching (C<spiderboy@spiderboy.net>).

This program is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.

=head1 CREDITS

Thanks to Tom Christiansen for Perl Cookbook recipe 14.5.

Thanks to Mark-Jason Dominus for the Perl Monger tutorial on file locking.

Thanks to David Harris and Paul Marquess for the recipe bug report.

Thanks to Chris Nandor for C<perlport>.

Thanks to James Wismer for feedback on the initial, unreleased version.

Thanks to Jay Trolley for her patience and understanding.

Thanks to xeenie for everything else.

=cut