Eric Wolf

NAME

 Data::RecordStore - Simple and fast record based data store

SYNPOSIS

 use Data::RecordStore;

 $store = Data::RecordStore->open_store( $directory );
 $data = "TEXT OR BINARY DATA";

 ### Without transactions ###

 my $id = $store->stow( $data );

 my $new_or_recycled_id = $store->next_id;
 $store->stow( $new_data, $new_or_recycled_id );

 my $val = $store->fetch( $some_id );

 my $count = $store->entry_count;

 $store->delete_record( $del_id );

 $store->recycle_id( $del_id );

 my $has_id = $store->has_id( $someother_id );

 $store->empty_recycler; #all recycled ids are gone

 $store->empty; # clears out store completely



 ### Using Transactions ###

 my $transaction = $store->create_transaction;

 print join(",", $transaction->get_update_time,
                 $transaction->get_process_id,
                 $transaction->get_state,
                 $transaction->get_id );

 my $new_id = $transaction->stow( $data );

 my $new_or_reused_id = $store->next_id;

 $transaction->stow( "MORE DATA", $new_or_reused_id );

 $transaction->delete_record( $someid );

 $transaction->recycle_id( $dead_id );

 if( $is_good ) {
    $transaction->commit;
 } else {
    $transaction->rollback;
 }


 ### Transaction maintenance ###

 # Get a list of transactions that are old and probably stale.
 for my $trans ($store->list_transactions) {

   next if $trans->get_udpate_time > $too_old;

   if( $trans->get_state == Data::RecordStore::Transaction::TRA_IN_COMMIT
     || $trans->get_state == Data::RecordStore::Transaction::TRA_CLEANUP_COMMIT )
   {
      $trans->commit;
   }
   elsif( $trans->get_state == Data::RecordStore::Transaction::TRA_IN_ROLLBACK
     || $trans->get_state == Data::RecordStore::Transaction::TRA_CLEANUP_ROLLBACK )
   {
      $trans->rollback;
   }
   elsif( $trans->get_state == Data::RecordStore::Transaction::TRA_ACTIVE )
   {
      # commit or rollback, depending on preference
   }
 }

DESCRIPTION

A simple and fast way to store arbitrary text or byte data. It is written entirely in perl with no non-core dependencies. It is designed to be both easy to set up and easy to use.

Transactions allow the RecordStore to protect data. Transactions can collect stow, delete_record and recycle_id actions. Data stowed this way is stored in the record store, but indexed to only by the transaction. Upon a transaction commit, the indexes are updated and discarded data removed. Destructive actions are only performed once the transaction updates the indexes.

Data is stored in fixed record file silos. This applies to index data, recycling data, payload data and transaction data. These silos are self vaccuuming. Entries that are removed either by deletion or recycling have their space in the file replaced by a live entry.

This is not a server or daemon, this is a direct operation on the file system. Only meta data such as directories, file location and fixed calculated values are stored as state. That means this is not thread safe. It can be used in a thread safe manner if a program using it provides locking mechanisms.

LIMITATIONS

Data::RecordStore is not thread safe. Thread coordination and locking can be done on a level above Data::RecordStore.

METHODS

open_store( directory, options )

Takes a single argument - a directory, and constructs the data store in it. The directory must be writeable or creatible. If a RecordStore already exists there, it opens it, otherwise it creates a new one.

Options

group - when files are created, they use this user group if able.

create_transaction()

Creates and returns a transaction object

list_transactions

Returns a list of currently existing transaction objects that are not marked TRA_DONE.

stow( data, optionalID )

This saves the text or byte data to the record store. If an id is passed in, this saves the data to the record for that id, overwriting what was there. If an id is not passed in, it creates a new record store.

Returns the id of the record written to.

fetch( id )

Returns the record associated with the ID. If the ID has no record associated with it, undef is returned.

entry_count

Returns how many active ids have been assigned in this store. If an ID was assigned but not used, it still counts towards the number of entries.

delete_record( id )

Removes the entry with the given id from the store, freeing up its space. It does not reuse the id.

has_id( id )

  Returns true if an record with this id exists in the record store.

next_id

This sets up a new empty record and returns the id for it.

empty()

This empties out the entire record store completely. Use only if you mean it.

empty_recycler()

  Clears out all data from the recycler

recycle( id, keep_data_flag )

  Ads the id to the recycler, so it will be returned when next_id is called.
  This removes the data occupied by the id, freeing up space unles keep_data_flag
  is set to true.

open( direcdtory )

Alias to open_store

delete( id )

Alias to delete_record

HELPER PACKAGES

Data::RecordStore relies on two helper packages that are useful in their own right and are documented here.

HELPER PACKAGE

Data::RecordStore::Silo

DESCRIPTION

A fixed record store that uses perl pack and unpack templates to store identically sized sets of data and uses a set of files to do so.

SYNOPSIS

 my $template = "LII"; # perl pack template. See perl pack/unpack.

 my $size; #required if the template does not have a definite size, like A*

 my $store = Data::RecordStore::Silo->open_silo( $template, $filename, $size );

 my $new_id = $store->next_id;

 $store->put_record( $new_id, [ 321421424243, 12, 345 ] );

 my $more_data = $store->get_record( $other_id );

 my $removed_last = $store->pop;

 my $last_id = $store->push( $data_for_the_end );

 my $entries = $store->entry_count;

 $store->emtpy;

 $store->unlink_store;

METHODS

open_silo( template, filename, record_size, options )

Opens or creates the directory for a group of files that represent one silo storing records of the given template and size. If a size is not given, it calculates the size from the template, if it can. This will die if a zero byte record size is given or calculated.

Options

group - when files are created, they use this user group if able.

empty

This empties out the database, setting it to zero records.

Returns the number of entries in this store. This is the same as the size of the file divided by the record size.

get_record( idx )

Returns an arrayref representing the record with the given id. The array in question is the unpacked template.

next_id

adds an empty record and returns its id, starting with 1

pop

Remove the last record and return it.

last_entry

Return the last record.

push( data )

Add a record to the end of this store. Returns the id assigned to that record. The data must be a scalar or list reference. If a list reference, it should conform to the pack template assigned to this store.

push( idx, data )

Saves the data to the record and the record to the filesystem. The data must be a scalar or list reference. If a list reference, it should conform to the pack template assigned to this store.

Removes the file for this record store entirely from the file system.

open( direcdtory )

Alias to open_silo

HELPER PACKAGE

Data::RecordStore::Transaction

DESCRIPTION

A transaction that can collect actions on the record store and then writes them as a block.

SYNOPSIS

my $trans = $store->create_transaction;

print join(",", $transaction->get_update_time, $transaction->get_process_id, $transaction->get_state, $transaction->get_id );

my $new_id = $transaction->stow( $data );

my $new_or_recycled_id = $store->next_id;

$transaction->stow( "MORE DATA", $new_or_recycled_id );

$transaction->delete_record( $someid ); $transaction->recycle_id( $dead_id );

if( $is_good ) { $transaction->commit; } else { $transaction->rollback; } # # Get a list of transactions that are old and probably stale. # for my $trans ($store->list_transactions) {

  next if $trans->get_udpate_time > $too_old;

  if( $trans->get_state == Data::RecordStore::Transaction::TRA_IN_COMMIT
    || $trans->get_state == Data::RecordStore::Transaction::TRA_CLEANUP_COMMIT )
  {
     $trans->commit;
  }
  elsif( $trans->get_state == Data::RecordStore::Transaction::TRA_IN_ROLLBACK
    || $trans->get_state == Data::RecordStore::Transaction::TRA_CLEANUP_ROLLBACK )
  {
     $trans->rollback;
  }
  elsif( $trans->get_state == Data::RecordStore::Transaction::TRA_ACTIVE )
  {
     # commit or rollback, depending on preference
  }
}

METHODS

get_update_time

Returns the epoch time when the last time this was updated.

get_process_id

Returns the process id that last wrote to this transaction.

get_state

Returns the state of this process. Values are TRA_ACTIVE TRA_IN_COMMIT TRA_IN_ROLLBACK TRA_COMMIT_CLEANUP TRA_ROLLBACK_CLEANUP TRA_DONE

get_id

Returns the ID for this transaction, which is the same as its position in the transaction index plus one.

stow( $data, $optional_id )

Stores the data given. Returns the id that the data was stowed under. If the id is not given, this generates one from the record store. The data stored this way is really stored in the record store, but the index is not updated until a commit happens. That means it is not reachable from the store until the commit.

delete_record( $id )

Marks that the record associated with the id is to be deleted when the transaction commits.

recycle_id( $id )

Marks that the record associated with the id is to be deleted and its id recycled when the transaction commits.

commit()

Commit applies

Removes the file for this record store entirely from the file system.

AUTHOR Eric Wolf coyocanid@gmail.com

COPYRIGHT AND LICENSE

       Copyright (c) 2015-2018 Eric Wolf. All rights reserved.  This program is free software; you can redistribute it and/or modify it
       under the same terms as Perl itself.

VERSION Version 3.21 (April, 2018))

4 POD Errors

The following errors were encountered while parsing the POD:

Around line 163:

You forgot a '=back' before '=head3'

Around line 165:

'=item' outside of any '=over'

Around line 637:

You forgot a '=back' before '=head3'

Around line 639:

'=item' outside of any '=over'