http://paperlined.org/src/pl/jollies/backend/NeverTMPbackend_dbm.pm

package NeverTMPbackend_dbm;

    use strict;
    use warnings;

    use BerkeleyDB;
    use Storable;


    use Exporter;
    our @EXPORT = qw( $permdb $transdb );





our $permdb;        # permanent.db
our $transdb;       # transient.db

our %permdb;
our %transdb;


sub open_dbs {
    my $directory = shift or die "Please specify database location.";

    $permdb = tie %permdb, 'BerkeleyDB::Btree',
            -Filename => "$directory/permanent.db",
            -Flags    => DB_CREATE
                or die "Cannot open file $directory/permanent.db: $! $BerkeleyDB::Error\n" ;

    $transdb = tie %transdb, 'BerkeleyDB::Btree',
            -Filename => "$directory/transient.db",
            -Flags    => DB_CREATE
                or die "Cannot open file $directory/transient.db: $! $BerkeleyDB::Error\n" ;
}




# Add a new item to the end of a queue.
sub enqueue {
    my $db = shift;
    my $queue_prefix = shift;
    my $data = shift;

    $queue_prefix .= "\\";
    my $prefixlen = length($queue_prefix);
    my $lastKey = getLastSuffixKey($db, $queue_prefix) || "${queue_prefix}00000000";

    # increment the counter by one
    $lastKey = $queue_prefix . sprintf("%08d", int(substr($lastKey, $prefixlen)) + 1);
    
    $db->db_put($lastKey, Storable::freeze($data));

    return $lastKey;
}


sub dequeue_peek {
    my $db = shift;
    my $queue_prefix = shift;

    $queue_prefix .= "\\";
    my $prefixlen = length($queue_prefix);

    my $value;
    my $cursor = $db->db_cursor();
    my $key = $queue_prefix;
    if ($cursor->c_get($key, $value, DB_SET_RANGE) == 0) {
        if (substr($key, 0, $prefixlen) eq $queue_prefix) {
            $cursor->c_close();
            $db->db_get($key, $value);
            if (wantarray) {
                return ($key, Storable::thaw( $value ));
            } else {
                return Storable::thaw( $value );
            }
        }
    }

    $cursor->c_close();
    return undef;
}


sub dequeue {
    my ($key, $val) = dequeue_peek(@_);

    my $db = shift;
    $db->db_del($key);

    return $val;
}


sub get {
    my $db = shift;
    my $key = shift;

    my $val;
    $db->db_get($key, $val);
    return Storable::thaw( $val );
}

sub put {
    my $db = shift;
    my $key = shift;
    my $val = shift;

    $db->db_put($key, Storable::freeze($val) );
}



# a general-purpose utility function for 'BerkeleyDB'...  given a prefix, find the last key with
# that prefix  (as opposed to 'DB_SET_RANGE', which makes it easy to find the first)
sub getLastSuffixKey {
    my $db = shift;
    my $prefix = shift;

    my $prefixlen = length($prefix);

    my ($next_key, $value);
    my $cursor = $db->db_cursor();
    my $key = $prefix . chr(255) x 80;        # BTree is sorted in lexical order...  hopefully this is the last possible key?
    if ($cursor->c_get($key, $value, DB_SET_RANGE) == 0) {
        if (substr($key, 0, $prefixlen) eq $prefix) {
            $cursor->c_close();
            return $key;
        } elsif ($cursor->c_get($key, $value, DB_PREV) == 0) {
            if (substr($key, 0, $prefixlen) eq $prefix) {
                $cursor->c_close();
                return $key;
            }
        }
    } elsif ($cursor->c_get($key, $value, DB_LAST) == 0) {
        if (substr($key, 0, $prefixlen) eq $prefix) {
            $cursor->c_close();
            return $key;
        }
    }
    $cursor->c_close();

    return undef;   # didn't find it
}


1;

Generated by GNU enscript 1.6.4.