X-Git-Url: http://git.rot13.org/?p=perl-Redis.git;a=blobdiff_plain;f=lib%2FRedis.pm;h=8df6779a2d5b1ed08a897aaaedebcffa27a81bd0;hp=a35d14e9498c41942764b04a47db82f46f168fbb;hb=HEAD;hpb=bc7a707890951a9cea371a1691fd15b055dbca1b diff --git a/lib/Redis.pm b/lib/Redis.pm index a35d14e..8df6779 100644 --- a/lib/Redis.pm +++ b/lib/Redis.pm @@ -4,8 +4,9 @@ use warnings; use strict; use IO::Socket::INET; -use Data::Dump qw/dump/; +use Data::Dumper; use Carp qw/confess/; +use Encode; =head1 NAME @@ -13,14 +14,14 @@ Redis - perl binding for Redis database =cut -our $VERSION = '0.08'; +our $VERSION = '1.2001'; =head1 DESCRIPTION Pure perl bindings for L -This version support git version 0.08 of Redis available at +This version supports protocol 1.2 or later of Redis available at L @@ -34,27 +35,23 @@ with same peace of code with a little help of C. =head2 new - my $r = Redis->new; + my $r = Redis->new; # $ENV{REDIS_SERVER} or 127.0.0.1:6379 -=cut - -our $debug = $ENV{REDIS} || 0; + my $r = Redis->new( server => '192.168.0.1:6379', debug = 0 ); -our $sock; -my $server = '127.0.0.1:6379'; +=cut sub new { my $class = shift; - my $self = {}; - bless($self, $class); - - warn "# opening socket to $server"; + my $self = {@_}; + $self->{debug} ||= $ENV{REDIS_DEBUG}; - $sock ||= IO::Socket::INET->new( - PeerAddr => $server, + $self->{sock} = IO::Socket::INET->new( + PeerAddr => $self->{server} || $ENV{REDIS_SERVER} || '127.0.0.1:6379', Proto => 'tcp', ) || die $!; + bless($self, $class); $self; } @@ -65,6 +62,13 @@ my $bulk_command = { sadd => 1, srem => 1, sismember => 1, echo => 1, + getset => 1, + smove => 1, + zadd => 1, + zrem => 1, + zscore => 1, + zincrby => 1, + append => 1, }; # we don't want DESTROY to fallback into AUTOLOAD @@ -74,21 +78,26 @@ our $AUTOLOAD; sub AUTOLOAD { my $self = shift; + use bytes; + + my $sock = $self->{sock} || die "no server connected"; + my $command = $AUTOLOAD; $command =~ s/.*://; - warn "## $command ",dump(@_) if $debug; + warn "## $command ",Dumper(@_) if $self->{debug}; my $send; if ( defined $bulk_command->{$command} ) { my $value = pop; + $value = '' if ! defined $value; $send = uc($command) . ' ' . join(' ', @_) . ' ' - . length($value) + . length( $value ) . "\r\n$value\r\n" ; } else { @@ -100,7 +109,7 @@ sub AUTOLOAD { ; } - warn ">> $send" if $debug; + warn ">> $send" if $self->{debug}; print $sock $send; if ( $command eq 'quit' ) { @@ -109,62 +118,67 @@ sub AUTOLOAD { } my $result = <$sock> || die "can't read socket: $!"; - warn "<< $result" if $debug; + Encode::_utf8_on($result); + warn "<< $result" if $self->{debug}; my $type = substr($result,0,1); $result = substr($result,1,-2); if ( $command eq 'info' ) { my $hash; - foreach my $l ( split(/\r\n/, __sock_read_bulk($result) ) ) { + foreach my $l ( split(/\r\n/, $self->__read_bulk($result) ) ) { my ($n,$v) = split(/:/, $l, 2); $hash->{$n} = $v; } return $hash; } elsif ( $command eq 'keys' ) { - return split(/\s/, __sock_read_bulk($result)); + my $keys = $self->__read_bulk($result); + return split(/\s/, $keys) if $keys; + return; } if ( $type eq '-' ) { - confess $result; + confess "[$command] $result"; } elsif ( $type eq '+' ) { return $result; } elsif ( $type eq '$' ) { - return __sock_read_bulk($result); + return $self->__read_bulk($result); } elsif ( $type eq '*' ) { - return __sock_read_multi_bulk($result); + return $self->__read_multi_bulk($result); } elsif ( $type eq ':' ) { return $result; # FIXME check if int? } else { - confess "unknown type: $type", __sock_read_line(); + confess "unknown type: $type", $self->__read_line(); } } -sub __sock_read_bulk { - my $len = shift; - return undef if $len < 0; +sub __read_bulk { + my ($self,$len) = @_; + return if $len < 0; my $v; if ( $len > 0 ) { - read($sock, $v, $len) || die $!; - warn "<< ",dump($v),$/ if $debug; + read($self->{sock}, $v, $len) || die $!; + Encode::_utf8_on($v); + warn "<< ",Dumper($v),$/ if $self->{debug}; } my $crlf; - read($sock, $crlf, 2); # skip cr/lf + read($self->{sock}, $crlf, 2); # skip cr/lf return $v; } -sub __sock_read_multi_bulk { - my $size = shift; - return undef if $size < 0; +sub __read_multi_bulk { + my ($self,$size) = @_; + return if $size < 0; + my $sock = $self->{sock}; $size--; my @list = ( 0 .. $size ); foreach ( 0 .. $size ) { - $list[ $_ ] = __sock_read_bulk( substr(<$sock>,1,-2) ); + $list[ $_ ] = $self->__read_bulk( substr(<$sock>,1,-2) ); } - warn "## list = ", dump( @list ) if $debug; + warn "## list = ", Dumper( @list ) if $self->{debug}; return @list; } @@ -358,6 +372,14 @@ See also L for tie interface. my $info_hash = $r->info; +=head1 ENCODING + +Since Redis knows nothing about encoding, we are forcing utf-8 flag on all data received from Redis. +This change is introduced in 1.2001 version. + +This allows us to round-trip utf-8 encoded characters correctly, but might be problem if you push +binary junk into Redis and expect to get it back without utf-8 flag turned on. + =head1 AUTHOR Dobrica Pavlinusic, C<< >> @@ -408,7 +430,7 @@ L =head1 COPYRIGHT & LICENSE -Copyright 2009 Dobrica Pavlinusic, all rights reserved. +Copyright 2009-2010 Dobrica Pavlinusic, all rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.