RPi-WiringPi/lib/RPi/WiringPi/Meta.pm
package RPi::WiringPi::Meta;
use strict;
use warnings;
use Carp qw(croak);
use IPC::ShareLite qw(:flock);
use JSON::XS;
our $VERSION = '2.3633_03';
sub meta {
my ($self) = @_;
return $self->{meta_shm} if exists $self->{meta_shm};
my $shm = IPC::ShareLite->new(
-key => $self->{shm_key},
-create => 1,
-destroy => 0,
) or die "can't create shared memory segment: $!";
$self->{meta_shm} = $shm;
}
sub meta_key_check {
# this is a class method, and must be called on the class prior to creating
# a Pi object
my ($class, $key) = @_;
if (! defined $key){
croak "meta_key_check() requires a key sent in...\n";
}
$key = unpack('i', pack('A4', $key));
my $shm_check = shmget($key, 65536, 0);
return defined $shm_check ? 1 : 0;
}
sub meta_key {
my ($self) = @_;
return $self->meta->key;
}
sub meta_lock {
my ($self, $flags) = @_;
$flags = LOCK_EX if ! defined $flags;
$self->meta->lock($flags);
}
sub meta_unlock {
my ($self) = @_;
$self->meta->unlock;
}
sub meta_fetch {
my ($self) = @_;
my $json;
$json = $self->meta->fetch;
$json = "{}" if $json eq '';
my $perl = decode_json $json;
return $perl
}
sub meta_store {
my ($self, $data) = @_;
if (! defined $data){
croak "meta_store() requires a hash reference sent in...\n";
}
$self->meta->store(encode_json $data) or die $!;
}
sub meta_delete {
my ($self, $name) = @_;
if (! defined $name){
croak "when setting a metadata slot, you must send in a name\n";
}
$self->meta_lock;
my $shm = $self->meta_fetch;
delete $shm->{storage}{$name};
$self->meta_store($shm);
$self->meta_unlock;
}
sub meta_set {
my ($self, $name, $data) = @_;
if (! defined $name){
croak "when setting a metadata slot, you must send in a name\n";
}
if (ref $data ne 'HASH'){
croak "when setting a metadata slot, you must supply a hash reference\n";
}
$self->meta_lock;
my $shm = $self->meta_fetch;
$shm->{storage}{$name} = { %$data };
$self->meta_store($shm);
$self->meta_unlock;
}
sub meta_get {
my ($self, $name) = @_;
if (! defined $name){
croak "when getting a metadata slot, you must send in a name\n";
}
$self->meta_lock;
my $shm = $self->meta_fetch;
my $data = { %{ $shm->{storage}{$name} }};
$self->meta_unlock;
return $data;
}
sub meta_erase {
my ($self) = @_;
$self->meta_lock;
$self->meta_store({});
$self->meta_unlock;
}
sub _vim{1;};
1;
__END__
=head1 NAME
RPi::WiringPi::Meta - Shared memory meta data management for RPI::WiringPi
=head1 DESCRIPTION
This module contains various utilities for the shared memory storage area.
=head1 METHODS
=head2 meta
Instantiates and returns a shared memory object that stores the meta data.
=head2 meta_set($name, $href)
Adds a user-defined hash reference to the shared memory segment with it's key
named C<$name>.
Parameters:
$name
Mandatory, String: Any value that is a legitimate value for a hash key.
$href
Mandatory, Hash Reference: A hash reference that contains your data.
=head2 meta_get($name)
Retrieves a user-defined hash reference from the shared memory.
Parameters:
$name
Mandatory, String: The key name for the user defined data.
Returns: Hash reference.
=head2 meta_delete($name)
Deletes a user-defined shared memory segment.
Parameters:
$name
Mandatory, String: The key name for the user defined data to delete.
=head2 meta_fetch
NOTE: For most use cases, users should use the L</meta_get($name)> method as
opposed to this one.
Fetches and returns the shared memory data as a hash reference.
=head2 meta_store($data)
NOTE: For most use cases, users should use the L</meta_set($name, $href)> and
L</meta_delete($name)> methods as opposed to this one.
Serializes and stores the shared data.
Parameters:
$data
Mandatory, Hash Reference. The data to store (should be a modified version that
was retrieved using C<meta_fetch()>).
=head2 meta_lock($flags)
Although we do locking on each transaction internally, use this as a wrapper
around bulk transactions.
Parameters:
$flags
Mandatory, Integer. See L<flock|http://man7.org/linux/man-pages/man2/flock.2.html>
for details as to what's available here.
Default: If C<$flags> is not sent in, we default to an exclusive lock
(C<LOCK_EX>).
=head2 meta_unlock
Performs an unlock after you're done with C<meta_lock()>.
=head2 meta_key
Returns the shared memory key that links the object to the shared memory
segment.
=head2 meta_key_check($key)
Checks whether a shared memory segment with the key C<$key> exists or not.
Parameters:
$key
Mandatory, String: A four letter key to validate against. This will be converted
into its integer form internally.
Returns: True C<1> if the shared memory segment exists, and false C<0>
otherwise.
=head2 meta_erase
Completely erases and resets all meta data. Do not use this method lightly.
=head1 AUTHOR
Steve Bertrand, E<lt>steveb@cpan.orgE<gt>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2016-2019 by Steve Bertrand
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.18.2 or,
at your option, any later version of Perl 5 you may have available.