line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Storage Driver backend for memcached |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package CGI::Session::Driver::memcache; |
4
|
2
|
|
|
2
|
|
102664
|
use strict; |
|
2
|
|
|
|
|
6
|
|
|
2
|
|
|
|
|
84
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#use Carp; |
7
|
|
|
|
|
|
|
|
8
|
2
|
|
|
2
|
|
2432
|
use CGI::Session::Driver; |
|
2
|
|
|
|
|
4517
|
|
|
2
|
|
|
|
|
221
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
our $sess_space = "sessions"; |
11
|
|
|
|
|
|
|
our $memd_connerror = "Need a connection handle to live memcached\n"; |
12
|
|
|
|
|
|
|
our @ISA = ('CGI::Session::Driver'); |
13
|
|
|
|
|
|
|
our $VERSION = '0.10'; |
14
|
|
|
|
|
|
|
our $trace = 0; |
15
|
2
|
|
|
2
|
|
1319
|
BEGIN { |
16
|
|
|
|
|
|
|
# keep historical behavior |
17
|
2
|
|
|
2
|
|
17
|
no strict 'refs'; |
|
2
|
|
|
|
|
10
|
|
|
2
|
|
|
|
|
51
|
|
18
|
|
|
|
|
|
|
# WHY would we want unbuffered output ? Having this can mess up mod_perl runtime. |
19
|
|
|
|
|
|
|
# |
20
|
|
|
|
|
|
|
#$| = 1; |
21
|
|
|
|
|
|
|
# Introspect %INC to see if CGI::Session::Driver::memcache has been |
22
|
|
|
|
|
|
|
# loaded from expected install-location (Patch %INC if necessary) |
23
|
|
|
|
|
|
|
#if (!$INC{'CGI/Session/Driver/memcache.pm'}) {...} |
24
|
|
|
|
|
|
|
} |
25
|
|
|
|
|
|
|
#sub new {} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# Developer info: |
28
|
|
|
|
|
|
|
# - CGI::Session::new (as class / constructor method, forwards args to load) |
29
|
|
|
|
|
|
|
# - CGI::Session::load() (Create self-stub, parse_dsn(), _load_pluggables()) |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# CGI::Session::Driver init method to be called |
33
|
|
|
|
|
|
|
# merely validate a connection to memcached exists |
34
|
|
|
|
|
|
|
sub init { |
35
|
1
|
|
|
1
|
1
|
136106
|
my $self = shift; |
36
|
|
|
|
|
|
|
#DEBUG:print CGI::header('text/plain'); |
37
|
|
|
|
|
|
|
#DEBUG:require Data::Dumper;print(Dumper($self)); |
38
|
|
|
|
|
|
|
# Require Handle to memcached connection |
39
|
1
|
|
50
|
|
|
21
|
my $memd = $self->{'Handle'} || die($memd_connerror); |
40
|
1
|
50
|
|
|
|
6
|
if ($trace) { |
41
|
|
|
|
|
|
|
#die("Vary: Using Connection: $memd\n"); |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
# Must add ? |
44
|
|
|
|
|
|
|
# Problem: Because of shallow copy does not persist |
45
|
|
|
|
|
|
|
#$self->{'_DSN'}->{'driver'} = 'memcache'; |
46
|
|
|
|
|
|
|
# TODO: Optionally grab a connection to memcached |
47
|
|
|
|
|
|
|
# Cache::memcache->new('servers' => [$self->{'servers'}]); |
48
|
|
|
|
|
|
|
# Success (see Driver.pm) |
49
|
|
|
|
|
|
|
#$self->{'_STATUS'} = 55; |
50
|
1
|
|
|
|
|
3
|
return 1; |
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
# Combine Session space and ID for truly unique ID |
53
|
|
|
|
|
|
|
# TODO: Add self to have session instance specific $sess_space |
54
|
|
|
|
|
|
|
sub _useid { |
55
|
1
|
50
|
|
1
|
|
4
|
if ($trace) { |
56
|
0
|
|
|
|
|
0
|
require Data::Dumper; |
57
|
0
|
|
|
|
|
0
|
my @ci = caller(1); |
58
|
|
|
|
|
|
|
#print(Data::Dumper::Dumper(\@ci)); |
59
|
0
|
|
|
|
|
0
|
print("$ci[3] : useid: $sess_space:$_[0]\n");} |
60
|
|
|
|
|
|
|
# Allow instace specific ID-space prefix ??? |
61
|
|
|
|
|
|
|
# my $use_space = $_[1] && $_[1]->{'space'} ? $_[1]->{'space'} : $sess_space; |
62
|
1
|
|
|
|
|
7
|
"$sess_space:$_[0]"; |
63
|
|
|
|
|
|
|
} |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Retrieve Session (will be passed to deserializer) |
66
|
|
|
|
|
|
|
sub retrieve { |
67
|
0
|
|
|
0
|
1
|
0
|
my ($self, $sid) = @_; |
68
|
0
|
|
|
|
|
0
|
my $memd = $self->{'Handle'}; |
69
|
0
|
0
|
|
|
|
0
|
if ($trace) {print("retrieve: Using $memd\n");} |
|
0
|
|
|
|
|
0
|
|
70
|
0
|
0
|
|
|
|
0
|
if (!$memd) {die($memd_connerror);} |
|
0
|
|
|
|
|
0
|
|
71
|
|
|
|
|
|
|
# Return Session to be de-serialized |
72
|
0
|
|
|
|
|
0
|
my $r = $memd->get(_useid($sid)); |
73
|
0
|
0
|
|
|
|
0
|
if (!$r) {return(0);} |
|
0
|
|
|
|
|
0
|
|
74
|
0
|
|
|
|
|
0
|
return $r; |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# Store serialized session |
78
|
|
|
|
|
|
|
sub store { |
79
|
1
|
|
|
1
|
1
|
236
|
my ($self, $sid, $datastr) = @_; |
80
|
1
|
|
|
|
|
2
|
my $memd = $self->{'Handle'}; |
81
|
1
|
50
|
|
|
|
4
|
if (!$memd) {die($memd_connerror);} |
|
0
|
|
|
|
|
0
|
|
82
|
1
|
|
|
|
|
5
|
my $ok = $memd->set(_useid($sid), $datastr); |
83
|
|
|
|
|
|
|
#if (!$ok) {$self->set_error( "store(): \$dbh->do failed " . $dbh->errstr );} |
84
|
1
|
50
|
|
|
|
9
|
return $ok ? 1 : 0; |
85
|
|
|
|
|
|
|
} |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
# Remove Session |
88
|
|
|
|
|
|
|
sub remove { |
89
|
0
|
|
|
0
|
1
|
|
my ($self, $sid) = @_; |
90
|
0
|
|
|
|
|
|
my $memd = $self->{'Handle'}; |
91
|
0
|
0
|
|
|
|
|
if (!$memd) {die($memd_connerror);} |
|
0
|
|
|
|
|
|
|
92
|
0
|
|
|
|
|
|
$memd->delete(_useid($sid)); |
93
|
0
|
|
|
|
|
|
return 1; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# execute $coderef for each session id passing session id as the first and the only |
97
|
|
|
|
|
|
|
# argument |
98
|
|
|
|
|
|
|
sub traverse { |
99
|
0
|
|
|
0
|
1
|
|
my ($self, $coderef) = @_; |
100
|
0
|
|
|
|
|
|
die("Traversing unsupported for memcached (for obvious security reasons)"); |
101
|
|
|
|
|
|
|
} |
102
|
0
|
|
|
0
|
|
|
sub DESTROY {} |
103
|
|
|
|
|
|
|
1; |
104
|
|
|
|
|
|
|
__END__ |