CGI-Session-Driver-memcache

 view release on metacpan or  search on metacpan

memcache.pm  view on Meta::CPAN

# Storage Driver backend for memcached

package CGI::Session::Driver::memcache;
use strict;

#use Carp;

use CGI::Session::Driver;

our $sess_space = "sessions";
our $memd_connerror = "Need a connection handle to live memcached\n";
our @ISA        = ('CGI::Session::Driver');
our $VERSION    = '0.10';
our $trace = 0;
BEGIN {
    # keep historical behavior
    no strict 'refs';
    # WHY would we want unbuffered output ? Having this can mess up mod_perl runtime.
    # 
    #$| = 1;
    # Introspect %INC to see if CGI::Session::Driver::memcache has been
    # loaded from expected install-location (Patch %INC if necessary)
    #if (!$INC{'CGI/Session/Driver/memcache.pm'}) {...}
}
#sub new {}

# Developer info:
# - CGI::Session::new (as class / constructor method, forwards args to load)
#  - CGI::Session::load() (Create self-stub, parse_dsn(), _load_pluggables())


# CGI::Session::Driver init method to be called 
# merely validate a connection to memcached exists
sub init {
    my $self = shift;
    #DEBUG:print CGI::header('text/plain');
    #DEBUG:require Data::Dumper;print(Dumper($self));
    # Require Handle to memcached connection
    my $memd  = $self->{'Handle'} || die($memd_connerror);
    if ($trace) {
       #die("Vary: Using Connection: $memd\n");
    }
    # Must add ?
    # Problem: Because of shallow copy does not persist
    #$self->{'_DSN'}->{'driver'} = 'memcache';
    # TODO: Optionally grab a connection to memcached
    # Cache::memcache->new('servers' => [$self->{'servers'}]);
    # Success (see Driver.pm)
    #$self->{'_STATUS'} = 55;
    return 1;
}
# Combine Session space and ID for truly unique ID
# TODO: Add self to have session instance specific $sess_space
sub _useid {
   if ($trace) {
      require Data::Dumper;
      my @ci = caller(1);
      #print(Data::Dumper::Dumper(\@ci));
      print("$ci[3] : useid: $sess_space:$_[0]\n");}
   # Allow instace specific ID-space prefix ???
   # my $use_space = $_[1] && $_[1]->{'space'} ? $_[1]->{'space'} : $sess_space;
   "$sess_space:$_[0]";
}

# Retrieve Session (will be passed to deserializer)
sub retrieve {
    my ($self, $sid) = @_;
    my $memd = $self->{'Handle'};
    if ($trace) {print("retrieve: Using $memd\n");}
    if (!$memd) {die($memd_connerror);}
    # Return Session to be de-serialized
    my $r = $memd->get(_useid($sid));
    if (!$r) {return(0);}
    return $r;
}

# Store serialized session
sub store {
   my ($self, $sid, $datastr) = @_;
   my $memd = $self->{'Handle'};
   if (!$memd) {die($memd_connerror);}
   my $ok = $memd->set(_useid($sid),  $datastr);
   #if (!$ok) {$self->set_error( "store(): \$dbh->do failed " . $dbh->errstr );}
   return $ok ? 1 : 0;
}

# Remove Session
sub remove {
   my ($self, $sid) = @_;
   my $memd = $self->{'Handle'};
   if (!$memd) {die($memd_connerror);}
   $memd->delete(_useid($sid));
   return 1;
}

# execute $coderef for each session id passing session id as the first and the only
# argument
sub traverse {
   my ($self, $coderef) = @_;
   die("Traversing unsupported for memcached (for obvious security reasons)");
}
sub DESTROY {}
1;
__END__

=head1 NAME

CGI::Session::Driver::memcache - Store CGI::Session objects in memcache daemon

=head1 SYNOPSIS

  my $memd = new Cache::Memcached({
    servers => ['localhost:11211'],
  });
  if (!$memd) {die("No Connection to Memcached !");}

  my $cgi = CGI->new();



( run in 1.995 second using v1.01-cache-2.11-cpan-f56aa216473 )