#/*
# *  Copyright 2007 hkrn <hikarin@users.sourceforge.jp>
# *
# *  Licensed under the Apache License, Version 2.0 (the "License");
# *  you may not use this file except in compliance with the License.
# *  You may obtain a copy of the License at
# *
# *      http://www.apache.org/licenses/LICENSE-2.0
# *
# *  Unless required by applicable law or agreed to in writing, software
# *  distributed under the License is distributed on an "AS IS" BASIS,
# *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# *  See the License for the specific language governing permissions and
# *  limitations under the License.
# */
#
# $Id: Archive.pm 904 2007-07-18 13:31:12Z hikarin $
#

package Img0ch::Maple::Archive;

use strict;
use base qw(Img0ch::Maple::Simple);
use Fcntl qw();

sub load {
    my ( $iRepos, $path ) = @_;
    my $iKernel = $iRepos->{__kernel};
    my $data    = {};

    $path ||= $iRepos->{__filename};
    -r $path or return 1;
    local $!;

    eval {
        require PerlIO::gzip;
        open my $fh, '<', $path
            or $iKernel->throw_io_exception($path);
        binmode $fh, ':gzip';
        while ( my $line = <$fh> ) {
            chomp $line;
            my ( $key, $value ) = split '=', $line, 2;
            $data->{$key} = $value;
        }
        close $fh or $iKernel->throw_io_exception($path);
        $iRepos->{__perl_io_gzip_ok} = 1;
    };

    my $exception = $@;
    if ( $exception =~ m{img0ch\s*I/O\s*Exception} ) {
        die $exception, "\n";
    }
    else {
        require IO::Zlib;
        my $fh = IO::Zlib->new( $path, 'rb' )
            or $iKernel->throw_io_exception($path);
        while ( my $line = <$fh> ) {
            chomp $line;
            my ( $key, $value ) = split '=', $line, 2;
            $data->{$key} = $value;
        }
        $fh->close();
    }

    %{ $iRepos->{__data} } = %{$data};
    return 1;
}

sub save {
    my ( $iRepos, $path ) = @_;
    my $iKernel = $iRepos->{__kernel};
    my $data    = $iRepos->{__data};

    $path ||= $iRepos->{__filename};
    my $temp    = $path . '.tmp';
    my $LOCK_EX = 2;
    eval {
        require Fcntl;
        $LOCK_EX = Fcntl::LOCK_EX();
    };

    if ( $iRepos->{__perl_io_gzip_ok} ) {
        eval {
            local $!;
            open my $fh, '>', $temp
                or $iKernel->throw_io_exception($path);
            binmode $fh, ':gzip';
            flock $fh, $LOCK_EX;
            while ( my ( $key, $value ) = each %{$data} ) {
                print ${fh} $key, '=', $value, "\n"
                    or $iKernel->throw_io_exception($path);
            }
            close $fh or $iKernel->throw_io_exception($path);
            rename $temp, $path or $iKernel->throw_io_exception($path);
        };
        if ( my $exception = $@ ) {
            if ( -e $temp ) {
                unlink $temp or $iKernel->throw_io_exception($temp);
            }
            die $exception, "\n";
        }
    }
    else {
        eval {
            require IO::Zlib;
            my $fh = IO::Zlib->new( $temp, 'wb3' )
                or $iKernel->throw_io_exception($temp);
            while ( my ( $key, $value ) = each %{$data} ) {
                $fh->print( $key, '=', $value, "\n" )
                    or $iKernel->throw_io_exception($path);
            }
            $fh->close();
            rename $temp, $path or $iKernel->throw_io_exception($path);
        };
        if ( my $exception = $@ ) {
            if ( -e $temp ) {
                unlink $temp or $iKernel->throw_io_exception($temp);
            }
            die $exception, "\n";
        }
    }
    return 1;
}

1;
__END__
