line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package POE::Filter::Redis; |
2
|
|
|
|
|
|
|
BEGIN { |
3
|
1
|
|
|
1
|
|
599
|
$POE::Filter::Redis::VERSION = '0.02'; |
4
|
|
|
|
|
|
|
} |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
#ABSTRACT: A POE Filter for the Redis protocol |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
5
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
24
|
|
9
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
31
|
|
10
|
1
|
|
|
1
|
|
5
|
use Carp qw[carp croak]; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
72
|
|
11
|
1
|
|
|
1
|
|
4
|
use base qw[POE::Filter]; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
904
|
|
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
# Bit mask. |
14
|
|
|
|
|
|
|
use constant { |
15
|
1
|
|
|
|
|
115
|
PARSER_IDLE => 0x01, |
16
|
|
|
|
|
|
|
PARSER_BETWEEN_BULK => 0x02, |
17
|
|
|
|
|
|
|
PARSER_IN_BULK => 0x04, |
18
|
1
|
|
|
1
|
|
589
|
}; |
|
1
|
|
|
|
|
2
|
|
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
use constant { |
21
|
1
|
|
|
|
|
1234
|
SELF_BUFFER => 0, |
22
|
|
|
|
|
|
|
SELF_STATE => 1, |
23
|
|
|
|
|
|
|
SELF_HAS => 2, |
24
|
|
|
|
|
|
|
SELF_LENGTH => 3, |
25
|
|
|
|
|
|
|
SELF_AWAITING => 4, |
26
|
|
|
|
|
|
|
SELF_TYPE => 5, |
27
|
1
|
|
|
1
|
|
6
|
}; |
|
1
|
|
|
|
|
1
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
sub new { |
30
|
1
|
|
|
1
|
1
|
13
|
my $package = shift; |
31
|
|
|
|
|
|
|
|
32
|
1
|
|
|
|
|
3
|
my %args = @_; |
33
|
|
|
|
|
|
|
|
34
|
1
|
|
|
|
|
7
|
return bless [ |
35
|
|
|
|
|
|
|
'', # SELF_BUFFER |
36
|
|
|
|
|
|
|
PARSER_IDLE, # SELF_STATE |
37
|
|
|
|
|
|
|
[ ], # SELF_HAS |
38
|
|
|
|
|
|
|
0, # SELF_LENGTH |
39
|
|
|
|
|
|
|
0, # SELF_AWAITING |
40
|
|
|
|
|
|
|
undef, # SELF_TYPE |
41
|
|
|
|
|
|
|
], $package; |
42
|
|
|
|
|
|
|
} |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
sub get_one_start { |
45
|
52
|
|
|
52
|
1
|
36265
|
my ($self, $stream) = @_; |
46
|
52
|
|
|
|
|
93
|
$self->[SELF_BUFFER] .= join '', @{ $stream }; |
|
52
|
|
|
|
|
138
|
|
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
sub get_one { |
50
|
68
|
|
|
68
|
1
|
314
|
my $self = shift; |
51
|
|
|
|
|
|
|
|
52
|
68
|
100
|
100
|
|
|
431
|
return [ ] unless ( |
53
|
|
|
|
|
|
|
length $self->[SELF_BUFFER] and $self->[SELF_BUFFER] =~ /\x0D\x0A/ |
54
|
|
|
|
|
|
|
); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
# I expect it to be here mostly. |
57
|
28
|
100
|
|
|
|
65
|
if ($self->[SELF_STATE] & PARSER_IDLE) { |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# Single-line responses. Remain in PARSER_IDLE state. |
60
|
18
|
100
|
|
|
|
99
|
return [ [ $1, $2 ] ] if $self->[SELF_BUFFER] =~ s/^([-+:])(.*?)\x0D\x0A//s; |
61
|
|
|
|
|
|
|
|
62
|
12
|
100
|
|
|
|
63
|
if ($self->[SELF_BUFFER] =~ s/^\*(-?\d+)\x0D\x0A//) { |
|
|
50
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
# Zero-item multibulk is an empty list. |
65
|
|
|
|
|
|
|
# Remain in the PARSER_IDLE state. |
66
|
6
|
100
|
|
|
|
36
|
return [ [ '*', ] ] if $1 == 0; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# Negative item multibulk is an undef list. |
69
|
4
|
100
|
|
|
|
18
|
return [ [ '*', undef ] ] if $1 < 0; |
70
|
|
|
|
|
|
|
|
71
|
2
|
|
|
|
|
9
|
@$self[SELF_STATE, SELF_AWAITING, SELF_HAS, SELF_TYPE] = ( |
72
|
|
|
|
|
|
|
PARSER_BETWEEN_BULK, $1, [], '*' |
73
|
|
|
|
|
|
|
); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
elsif ($self->[SELF_BUFFER] =~ s/^\$(-?\d+)\x0D\x0A//) { |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# -1 length is undef. |
78
|
|
|
|
|
|
|
# Remain in the PARSER_IDLE state. |
79
|
6
|
100
|
|
|
|
22
|
return [ [ '$', undef ] ] if $1 < 0; |
80
|
|
|
|
|
|
|
|
81
|
4
|
|
|
|
|
18
|
@$self[SELF_STATE, SELF_AWAITING, SELF_LENGTH, SELF_HAS, SELF_TYPE] = ( |
82
|
|
|
|
|
|
|
PARSER_IN_BULK, 1, $1 + 2, [], '$' |
83
|
|
|
|
|
|
|
); |
84
|
|
|
|
|
|
|
} |
85
|
|
|
|
|
|
|
else { |
86
|
|
|
|
|
|
|
# TODO - Recover somehow. |
87
|
0
|
|
|
|
|
0
|
croak "illegal redis response:\n$self->[SELF_BUFFER]"; |
88
|
|
|
|
|
|
|
} |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
16
|
|
|
|
|
23
|
while (1) { |
92
|
20
|
100
|
|
|
|
46
|
if ($self->[SELF_STATE] & PARSER_BETWEEN_BULK) { |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
# Can't parse a bulk header? |
95
|
12
|
100
|
|
|
|
57
|
return [ ] unless $self->[SELF_BUFFER] =~ s/^\$(-?\d+)\x0D\x0A//; |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# -1 length is undef. |
98
|
6
|
100
|
|
|
|
22
|
if ($1 < 0) { |
99
|
2
|
50
|
|
|
|
4
|
if (push(@{$self->[SELF_HAS]}, undef) == $self->[SELF_AWAITING]) { |
|
2
|
|
|
|
|
10
|
|
100
|
0
|
|
|
|
|
0
|
$self->[SELF_STATE] = PARSER_IDLE; |
101
|
0
|
|
|
|
|
0
|
return [ [ $self->[SELF_TYPE], @{$self->[SELF_HAS]} ] ]; |
|
0
|
|
|
|
|
0
|
|
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# Remain in PARSER_BETWEEN_BULK state. |
105
|
2
|
|
|
|
|
4
|
next; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# Got a bulk length. |
109
|
4
|
|
|
|
|
14
|
@$self[SELF_STATE, SELF_LENGTH] = (PARSER_IN_BULK, $1 + 2); |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
# Fall through. |
112
|
|
|
|
|
|
|
} |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# TODO - Just for debugging.. |
115
|
12
|
50
|
|
|
|
29
|
croak "unexpected state $self->[SELF_STATE]" unless ( |
116
|
|
|
|
|
|
|
$self->[SELF_STATE] & PARSER_IN_BULK |
117
|
|
|
|
|
|
|
); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
# Not enough data? |
120
|
12
|
100
|
|
|
|
38
|
return [ ] if length $self->[SELF_BUFFER] < $self->[SELF_LENGTH]; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# Got a bulk value. |
123
|
8
|
100
|
|
|
|
8
|
if ( |
124
|
8
|
|
|
|
|
42
|
push( |
125
|
|
|
|
|
|
|
@{$self->[SELF_HAS]}, |
126
|
|
|
|
|
|
|
substr( |
127
|
|
|
|
|
|
|
substr($self->[SELF_BUFFER], 0, $self->[SELF_LENGTH], ''), |
128
|
|
|
|
|
|
|
0, $self->[SELF_LENGTH] - 2 |
129
|
|
|
|
|
|
|
) |
130
|
|
|
|
|
|
|
) == $self->[SELF_AWAITING] |
131
|
|
|
|
|
|
|
) { |
132
|
6
|
|
|
|
|
8
|
$self->[SELF_STATE] = PARSER_IDLE; |
133
|
6
|
|
|
|
|
10
|
return [ [ $self->[SELF_TYPE], @{$self->[SELF_HAS]} ] ]; |
|
6
|
|
|
|
|
27
|
|
134
|
|
|
|
|
|
|
} |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# But... not enough of them. |
137
|
2
|
|
|
|
|
5
|
$self->[SELF_STATE] = PARSER_BETWEEN_BULK; |
138
|
|
|
|
|
|
|
} |
139
|
|
|
|
|
|
|
|
140
|
0
|
|
|
|
|
0
|
croak "never gonna give you up, never gonna let you down"; |
141
|
|
|
|
|
|
|
} |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
sub get_pending { |
144
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
145
|
0
|
0
|
|
|
|
0
|
return [ $self->[SELF_BUFFER] ] if length $self->[SELF_BUFFER]; |
146
|
0
|
|
|
|
|
0
|
return undef; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub put { |
150
|
4
|
|
|
4
|
1
|
2787
|
my ($self,$cmds) = @_; |
151
|
|
|
|
|
|
|
|
152
|
4
|
|
|
|
|
6
|
my @raw; |
153
|
4
|
|
|
|
|
7
|
foreach my $line ( @{ $cmds } ) { |
|
4
|
|
|
|
|
8
|
|
154
|
4
|
50
|
|
|
|
13
|
next unless ref $line eq 'ARRAY'; |
155
|
4
|
50
|
|
|
|
6
|
next unless scalar @{ $line }; |
|
4
|
|
|
|
|
39
|
|
156
|
4
|
|
|
|
|
5
|
my $cmd = shift @{ $line }; |
|
4
|
|
|
|
|
9
|
|
157
|
4
|
|
|
|
|
11
|
push @raw, |
158
|
|
|
|
|
|
|
join( "\x0D\x0A", |
159
|
8
|
|
|
|
|
38
|
'*' . ( 1 + @{ $line } ), |
160
|
4
|
|
|
|
|
10
|
map { ('$' . length $_ => $_) } |
161
|
4
|
|
|
|
|
8
|
( uc($cmd), @{ $line } ) ) . "\x0D\x0A"; |
162
|
|
|
|
|
|
|
} |
163
|
4
|
|
|
|
|
27
|
\@raw; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
qq[Redis Filter]; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# vim: ts=2 sw=2 expandtab |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
__END__ |