Bot-Cobalt

 view release on metacpan or  search on metacpan

lib/Bot/Cobalt/Serializer.pm  view on Meta::CPAN

}



sub _check_if_avail {
  my ($self, $type) = @_;

  my $module;
  return unless $module = $self->_types->{$type};

  {
    local $@;
    eval "require $module";
    return if $@;
  }

  return $module
}


sub _read_serialized {
  my ($self, $path, $opts) = @_;
  return unless defined $path;

  my $lock = 1;
  if (defined $opts && ref $opts && reftype $opts eq 'HASH') {
    $lock = $opts->{Locking} if defined $opts->{Locking};
  }

  if (blessed $path && $path->can('slurp_utf8')) {
    return $path->slurp_utf8
  } else {
    open(my $in_fh, '<:encoding(UTF-8)', $path)
      or confess "open failed for $path: $!";

    if ($lock) {
      flock($in_fh, LOCK_SH)
        or confess "LOCK_SH failed for $path: $!";
     }

    my $data = join '', <$in_fh>;

    flock($in_fh, LOCK_UN) if $lock;

    close($in_fh)
      or carp "close failed for $path: $!";

    return $data
  }
}

sub _write_serialized {
  my ($self, $path, $data, $opts) = @_;
  return unless $path and defined $data;

  my $lock    = 1;
  my $timeout = 2;

  if (defined $opts && ref $opts && reftype $opts eq 'HASH') {
    $lock    = $opts->{Locking} if defined $opts->{Locking};
    $timeout = $opts->{Timeout} if $opts->{Timeout};
  }

  open(my $out_fh, '>>:encoding(UTF-8)', $path)
    or confess "open failed for $path: $!";

  if ($lock) {
    my $timer = 0;

    until ( flock $out_fh, LOCK_EX | LOCK_NB ) {
      confess "Failed writefile lock ($path), timed out ($timeout)"
        if $timer > $timeout;

      sleep 0.01;
      $timer += 0.01;
    }

  }

  seek($out_fh, 0, 0)
    or confess "seek failed for $path: $!";
  truncate($out_fh, 0)
    or confess "truncate failed for $path";

  print $out_fh $data;

  flock($out_fh, LOCK_UN) if $lock;

  close($out_fh)
    or carp "close failed for $path: $!";

  return 1
}

1;
__END__

=pod

=head1 NAME

Bot::Cobalt::Serializer - Bot::Cobalt serialization wrapper

=head1 SYNOPSIS

  use Bot::Cobalt::Serializer;

  ## Spawn a YAML (1.1) handler:
  my $serializer = Bot::Cobalt::Serializer->new;

  ## Spawn a JSON handler:
  my $serializer = Bot::Cobalt::Serializer->new('JSON');
  ## ...same as:
  my $serializer = Bot::Cobalt::Serializer->new( Format => 'JSON' );

  ## Serialize some data to our Format:
  my $ref = { Stuff => { Things => [ 'a', 'b'] } };
  my $frozen = $serializer->freeze( $ref );

  ## Turn it back into a Perl data structure:
  my $thawed = $serializer->thaw( $frozen );

lib/Bot/Cobalt/Serializer.pm  view on Meta::CPAN

=item *

B<YAML> - YAML1.0 via L<YAML::Syck>

=item *

B<YAMLXS> - YAML1.1 via L<YAML::XS>  I<(default)>

=item *

B<JSON> - JSON via L<JSON::MaybeXS>

=back

The default is YAML I<(YAML Ain't Markup Language)> 1.1 (B<YAMLXS>)

YAML is very powerful, and the appearance of the output makes it easy for 
humans to read and edit.

JSON is a more simplistic format, often more suited for network transmission 
and talking to other networked apps. JSON is noticably faster than YAML.

=head2 freeze

Turn the specified reference I<$ref> into the configured B<Format>.

  my $frozen = $serializer->freeze($ref);

Upon success returns a scalar containing the serialized format, suitable for 
saving to disk, transmission, etc.


=head2 thaw

Turn the specified serialized data (stored in a scalar) back into a Perl 
data structure.

  my $ref = $serializer->thaw($data);


(Try L<Data::Dumper> if you're not sure what your data actually looks like.)


=head2 writefile

L</freeze> the specified C<$ref> and write the serialized data to C<$path>

  $serializer->writefile($path, $ref);

Will croak with a stack trace if the specified path/data could not be 
written to disk due to an error.

Locks the file by default; blocks for up to 2 seconds attempting to 
gain a lock. You can turn this behavior off entirely:

  $serializer->writefile($path, $ref, { Locking => 0 });

... or change the lock timeout (defaults to 2 seconds):

  $serializer->writefile($path, $ref,
    { Locking => 1, Timeout => 5 }
  );


=head2 readfile

Read the serialized file at the specified C<$path> (if possible) and 
L</thaw> the data structures back into a reference.

  my $ref = $serializer->readfile($path);

By default, attempts to gain a shared (LOCK_SH) lock on the file in a 
blocking manner.
You can turn this behavior off:

  $serializer->readfile($path, { Locking => 0 });

Will croak with a stack trace if $path cannot be read or deserialized.


=head2 version

Obtains the backend serializer and its VERSION for the current instance.

  my ($module, $modvers) = $serializer->version;

Returns a list of two values: the module name and its version.

  ## via Devel::REPL:
  $ Bot::Cobalt::Serializer->new->version
  $VAR1 = 'YAML::Syck';
  $VAR2 = 1.19;


=head1 SEE ALSO

=over

=item *

L<YAML::Syck> -- YAML1.0: L<http://yaml.org/spec/1.0/>

=item *

L<YAML::XS> -- YAML1.1: L<http://yaml.org/spec/1.1/>

=item *

L<JSON>, L<JSON::MaybeXS> -- JSON: L<http://www.json.org/>

=back


=head1 AUTHOR

Jon Portnoy <avenj@cobaltirc.org>

=cut



( run in 1.395 second using v1.01-cache-2.11-cpan-39bf76dae61 )