| 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__ |