perl client api changes

Cahill, Earl ecahill at
Wed Jun 15 13:19:36 PDT 2005

I have a few changes that I want to present, and pending feedback, I
will send a nice little patch file.  Right now I have my own
which does


use base 'Cache::Memcached';


so, I can't really generate a nice little patch file right now.  My
version is "1.14".  Anyway, most of these changes center around escaping
characters in the key.  It looks like at least \s needs to get escaped.
And we're doing this


my %ord_cache = ();

for(0 .. 255) { $ord_cache{chr $_} = sprintf("%%%02X", $_); }


sub key_escape {


    $$key =~ s/([\s%])/$ord_cache{$1}/g;




To do the escaping.  And


my %chr_cache = ();

foreach(keys %ord_cache) {$chr_cache{$ord_cache{$_}} = $_};


$$key =~ s/(\%[0-9A-F]{2})/$chr_cache{$1}/g;



To do the unescaping.  We are currently escaping [^\/\w\.\-\ \@\:], but
it looks like [\s%] might do the trick.  The proper escape/unescapes
then get put into set, get_multi (since get wraps around get_multi), and
delete.  Not sure where else they would need to go, but I guess at least
add.  Also wondering about long keys.  I would like to at least get a
warning about how long keys just aren't going to work.


The following code should duplicate the current problems I am seeing


use Cache::Memcached;


my $old_mc = Cache::Memcached->new({ servers => [ 'localhost:11211' ],



  foreach my $key ("fred carter", "fred ", "fred\ncarter", "x" x 251) {

    check($old_mc, $key);




sub check {

  my $self = shift;

  my $key = shift || die "please send a key";

  my $value = shift || 'that';

  $self->set($key, $value);

  my $back = $self->get($key) || '';

  warn "'$key': '$value' ne '$back'" unless($value eq $back);





Another change comes with incr, and I think I have mentioned this one
before.  I found that I can't incr on an undefined key, so if I do this


sub incr {

  my $self = shift;

  my $key = shift;

  my $value = shift || 1;

  unless($self->SUPER::incr($key, $value)) {

    $self->add($key, 0);

    $self->SUPER::incr($key, $value);




It works.  Are people really doing that?  Also hitting me that I would
need to escape that key.


Also wondering about getting a set_multi to work, maybe just getting it
to work under normal set.  I would like to pass a hash ref to set and
have it do a set for each key/value pair in the hash ref.   I don't see
a scenario where a hash ref is sent to set, so I think it could squeeze
in there.  I don't currently have this one working, but I would be happy
to help out if needs be.


I also wrote this stats method, that seems to actually work.  I couldn't
really get the normal stats stuff going.  It compiles stats from all the
servers in $self->{servers}


sub mystats {

  my $self = shift;

  my $stats_hash = {};

  foreach my $host (@{$self->{servers}}) {


    my ($this_host, $this_port) = split /:/, $host;

    require IO::Socket;

    my $socket = IO::Socket::INET->new(

      Proto         => 'tcp',

      PeerAddr => $this_host,

      PeerPort => $this_port,



    print $socket "stats\n";

    my $hash = {};

    while(<$socket>) {


      if(/^STAT\s+(\w+)\s+(.+)/) {

        my ($key, $value) = ($1, $2);

        next if($key =~ /^(pid|time|version)$/);

        $hash->{$key} = $value;

        $stats_hash->{$key} += $value;

      } elsif(/^END/) {


      } else {

        die "bad line: $_";




  my $denoms = {

      hosts  => [qw(bytes connection_structures curr_connections
curr_items limit_maxbytes uptime)],

      uptime => [qw(bytes_read bytes_written cmd_get cmd_set get_hits
get_misses total_connections total_items)],


  my $report_hash = {};

  foreach my $denom (keys %{$denoms}) {

    foreach my $num (@{$denoms->{$denom}}) {

      $report_hash->{"$num / $denom"} = $stats_hash->{$num} /



  return ($stats_hash, $report_hash);



Anyway, feedback welcome.




-------------- next part --------------
An HTML attachment was scrubbed...

More information about the memcached mailing list