Alien::Libjio - Utility package to install and locate libjio


Alien-Libjio documentation Contained in the Alien-Libjio distribution.

Index


Code Index:

NAME

Top

Alien::Libjio - Utility package to install and locate libjio

VERSION

Top

version 1.004

SYNOPSIS

Top

  use Alien::Libjio;

  my $jio = Alien::Libjio->new;
  my $ldflags = $jio->ldflags;
  my $cflags = $jio->cflags;

DESCRIPTION

Top

To ensure reliability, some file systems and databases provide support for something known as journalling. The idea is to ensure data consistency by creating a log of actions to be taken (called a Write Ahead Log) before committing them to disk. That way, if a transaction were to fail due to a system crash or other unexpected event, the write ahead log could be used to finish writing the data.

While this functionality is often available with networked databases, it can be a rather memory- and processor-intensive solution, even where reliable writes are important. In other cases, the filesystem does not provide native journalling support, so other tricks may be used to ensure data integrity, such as writing to a separate temporary file and then overwriting the file instead of modifying it in-place. Unfortunately, this method cannot handle threaded operations appropriately.

Thankfully, Alberto Bertogli published a userspace C library called libjio that can provide these features in a small (less than 1500 lines of code) library with no external dependencies.

This package is designed to install it, and provide a way to get the flags necessary to compile programs using it. It is particularly useful for Perl XS programs that use it, such as IO::Journal.

METHODS

Top

Alien::Libjio->new

Creates a new Alien::Libjio object, which essentially just has a few convenience methods providing useful information like compiler and linker flags.

Example code:

  my $jio = Alien::Libjio->new();

This method will return an appropriate Alien::Libjio object or throw an exception on error.

$jio->installed

Determine if a valid installation of libjio has been detected in the system. This method will return a true value if it is, or undef otherwise.

Example code:

  print "okay\n" if $jio->installed;

$jio->version

Determine the installed version of libjio, as a string.

Currently versions are simply floating-point numbers, so you can treat the version number as such, but this behaviour is subject to change.

Example code:

  my $version = $jio->version;

$jio->ldflags

$jio->linker_flags

This returns the flags required to link C code with the local installation of libjio (typically in the LDFLAGS variable). It is particularly useful for building and installing Perl XS modules such as IO::Journal.

In scalar context, it returns an array reference suitable for passing to other build systems, particularly Module::Build. In list context, it gives a normal array so that join and friends will work as expected.

Example code:

  my $ldflags = $jio->ldflags;
  my @ldflags = @{ $jio->ldflags };
  my $ldstring = join(' ', $jio->ldflags);
  # or:
  # my $ldflags = $jio->linker_flags;

$jio->cflags

$jio->compiler_flags

This method returns the compiler option flags to compile C code which uses the libjio library (typically in the CFLAGS variable). It is particularly useful for building and installing Perl XS modules such as IO::Journal.

Example code:

  my $cflags = $jio->cflags;
  my @cflags = @{ $jio->cflags };
  my $ccstring = join(' ', $jio->cflags);
  # or:
  # my $cflags = $jio->compiler_flags;

$jio->method

$jio->how

This method returns the method the module used to find information about libjio. The following methods are currently used (in priority order):

Example code:

  if ($jio->installed) {
    print 'I found this information using: ', $jio->how, "\n";
  }

ACKNOWLEDGEMENTS

Top

SEE ALSO

Top

IO::Journal, a Perl module that provides an interface to libjio.

http://blitiri.com.ar/p/libjio/, Alberto Bertogli's page about libjio, which explains the purpose and features of libjio.

CAVEATS

Top

1;

BUGS

Top

Please report any bugs or feature requests on the bugtracker website http://rt.cpan.org/NoAuth/Bugs.html?Dist=Alien-Libjio

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

AUTHOR

Top

Jonathan Yu <jawnsy@cpan.org>

COPYRIGHT AND LICENSE

Top


Alien-Libjio documentation Contained in the Alien-Libjio distribution.

package Alien::Libjio;
BEGIN {
  $Alien::Libjio::VERSION = '1.004';
}
# ABSTRACT: Utility package to install and locate libjio

use strict;
use warnings;
use Carp ();


sub new {
  my ($class, @seed) = @_;

  Carp::croak('You must call this as a class method') if ref($class);

  my $self = {
    installed => 0,
  };

  bless($self, $class);

  $self->_try_pkg_config()
    or $self->_try_liblist()
    or delete($self->{method});

  return $self;
}


sub installed {
  my ($self) = @_;

  Carp::croak('You must call this method as an object') unless ref($self);

  return $self->{installed};
}


sub version {
  my ($self) = @_;

  Carp::croak('You must call this method as an object') unless ref($self);

  return $self->{version};
}


sub ldflags {
  my ($self) = @_;

  Carp::croak('You must call this method as an object') unless ref($self);

  # Return early if called in void context
  return unless defined wantarray;

  # If calling in array context, dereference and return
  return @{ $self->{ldflags} } if wantarray;

  return $self->{ldflags};
}

# Glob to create an alias to ldflags
*linker_flags = *ldflags;


sub cflags {
  my ($self) = @_;

  Carp::croak('You must call this method as an object') unless ref($self);

  # Return early if called in void context
  return unless defined wantarray;

  # If calling in array context, dereference and return
  return @{ $self->{cflags} } if wantarray;

  return $self->{cflags};
}
*compiler_flags = *cflags;


sub method {
  my ($self) = @_;

  Carp::croak('You must call this method as an object') unless ref($self);

  return $self->{method};
}
*how = *method;

# Private methods to find & fill out information

use IPC::Open3 ('open3');

sub _get_pc {
  my ($key) = @_;

  my $read;
  my $pid = open3(undef, $read, undef, 'pkg-config', 'libjio', '--' . $key);
  # We're using blocking wait, so the return value doesn't matter
  ## no critic(RequireCheckedSyscalls)
  waitpid($pid, 0);

  # Check the exit status; 0 = success - nonzero = failure
  if (($? >> 8) == 0) {
    # The value we got back
    return <$read>;
  }
  return (undef, <$read>) if wantarray;
  return;
}

sub _try_pkg_config {
  my ($self) = @_;

  my ($value, $err) = _get_pc('cflags');
  return unless (defined $value && length $value);
  #if (defined $err && length $err) {
  #  #warn "Problem with pkg-config; using ExtUtils::Liblist instead\n";
  #  return;
  #}

  $self->{installed} = 1;
  $self->{method} = 'pkg-config';

  # pkg-config returns things with a newline, so remember to remove it
  $self->{cflags} = [ split(' ', $value) ];
  $self->{ldflags} = [ split(' ', _get_pc('libs')) ];
  $self->{version} = _get_pc('modversion');

  return 1;
}

sub _try_liblist {
  my ($self) = @_;

  use ExtUtils::Liblist ();
  local $SIG{__WARN__} = sub { }; # mask warnings

  my (undef, undef, $ldflags, $ldpath) = ExtUtils::Liblist->ext('-ljio');
  return unless (defined($ldflags) && length($ldflags));

  $self->{installed} = 1;
  $self->{method} = 'ExtUtils::Liblist';

  # Empty out cflags; initialize it
  $self->{cflags} = [];

  my $read;
  my $pid = open3(undef, $read, undef, 'getconf', 'LFS_CFLAGS');

  # We're using blocking wait, so the return value doesn't matter
  ## no critic(RequireCheckedSyscalls)
  waitpid($pid, 0);

  # Check the status code
  if (($? >> 8) == 0) {
    # This only takes the first line
    push(@{ $self->{cflags} }, split(' ', <$read>));
  }
  else {
    warn 'Problem using getconf: ', <$read>, "\n";
    push(@{ $self->{cflags} },
      '-D_LARGEFILE_SOURCE',
      '-D_FILE_OFFSET_BITS=64',
    );
  }

  # Used for resolving the include path, relative to lib
  use Cwd ();
  use File::Spec ();
  push(@{ $self->{cflags} },
    # The include path is taken as: $libpath/../include
    '-I' . Cwd::realpath(File::Spec->catfile(
      $ldpath,
      File::Spec->updir(),
      'include'
    ))
  );

  push(@{ $self->{ldflags} },
    '-L' . $ldpath,
    $ldflags,
  );

  return 1;
}


__END__