=head1 NAME

EPrints::Plugin::Storage::LocalCompress - storage on the local disk

=head1 DESCRIPTION

See L<EPrints::Plugin::Storage> for available methods.

=head1 METHODS

=over 4

=cut

package EPrints::Plugin::Storage::LocalCompress;

use strict;

use URI;
use URI::Escape;

use EPrints::Plugin::Storage::Local;

use constant BUF_SIZE => 65536;

our @ISA = ( "EPrints::Plugin::Storage::Local" );

our $DISABLE = eval "use PerlIO::gzip; return 1" ? 0 : 1;

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

	my $self = $class->SUPER::new( %params );

	$self->{name} = "Compressed local disk storage";
	$self->{storage_class} = "a_local_disk_storage";

	return $self;
}

sub open_write
{
	my( $self, $fileobj ) = @_;

	return 0 if !$self->SUPER::open_write( $fileobj );

	my $fh = $self->{_fh}->{$fileobj};
	binmode( $fh, ":gzip" ) or die "Setting gzip IO layer failed: $!";

	return 1;
}

sub write
{
	my( $self, $fileobj, $buffer ) = @_;

	use bytes;

	my $fh = $self->{_fh}->{$fileobj}
		or Carp::croak "Must call open_write before write";

	if( !print $fh $buffer ) # sysread ignores gzip layer
	{
		my $path = $self->{_path}->{$fileobj};
		my $fn = $self->{_name}->{$fileobj};
		unlink("$path/$fn");
		$self->{error} = "Error writing to $path/$fn: $!";
		$self->{session}->get_repository->log( $self->{error} );
		return 0;
	}

	return 1;
}

sub open_read
{
	my( $self, $fileobj, $sourceid, $f ) = @_;

	return 0 if !$self->SUPER::open_read( $fileobj, $sourceid, $f );

	my $fh = $self->{_fh}->{$fileobj};
	binmode( $fh, ":gzip" ) or die "Setting gzip IO layer failed: $!";

	return 1;
}

sub retrieve
{
	my( $self, $fileobj, $sourceid, $offset, $n, $f ) = @_;

	return 0 if !$self->open_read( $fileobj, $sourceid, $f );
	my( $path, $fn ) = $self->_filename( $fileobj, $sourceid );

	return undef if !defined $path;

	my $fh = $self->{_fh}->{$fileobj};

	my $rc = 1;

	my $buffer;

	# sysread ignores gzip layer

	# sequentially move file position to $offset
	while($rc && $offset >= BUF_SIZE)
	{
		$offset -= BUF_SIZE;
		$rc &&= read($fh,$buffer,BUF_SIZE);
	}
	if( $offset )
	{
		$rc &&= read($fh,$buffer,$offset);
	}

	# read the requested chunk
	while($rc && $n >= BUF_SIZE && read($fh,$buffer,BUF_SIZE))
	{
		$n -= BUF_SIZE;
		$rc &&= &$f($buffer);
	}
	if($rc && read($fh,$buffer,$n))
	{
		$rc &&= &$f($buffer);
	}

	$self->close_read( $fileobj, $sourceid, $f );

	return $rc;
}

sub get_local_copy
{
	return &EPrints::Plugin::Storage::get_local_copy( @_ );
}

sub _filename
{
	my( $self, $fileobj, $sourceid ) = @_;

	my( $path, $fn ) = $self->SUPER::_filename( $fileobj, $sourceid );

	return if !defined $path;

	if( !defined $sourceid ) # file creation only
	{
		$fn .= '.gz';
	}

	return( $path, $fn );
}

=back

=cut

1;

=head1 COPYRIGHT

=for COPYRIGHT BEGIN

Copyright 2022 University of Southampton.
EPrints 3.4 is supplied by EPrints Services.

http://www.eprints.org/eprints-3.4/

=for COPYRIGHT END

=for LICENSE BEGIN

This file is part of EPrints 3.4 L<http://www.eprints.org/>.

EPrints 3.4 and this file are released under the terms of the
GNU Lesser General Public License version 3 as published by
the Free Software Foundation unless otherwise stated.

EPrints 3.4 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with EPrints 3.4.
If not, see L<http://www.gnu.org/licenses/>.

=for LICENSE END

