line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package RedisDB::Parser; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
137613
|
use strict; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
104
|
|
4
|
3
|
|
|
3
|
|
15
|
use warnings; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
124
|
|
5
|
|
|
|
|
|
|
our $VERSION = "2.21"; |
6
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
7
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
1578
|
use Try::Tiny; |
|
3
|
|
|
|
|
2122
|
|
|
3
|
|
|
|
|
462
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
my $implementation; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
unless ( $ENV{REDISDB_PARSER_PP} ) { |
13
|
|
|
|
|
|
|
try { |
14
|
|
|
|
|
|
|
require RedisDB::Parser::XS; |
15
|
|
|
|
|
|
|
$implementation = "RedisDB::Parser::XS"; |
16
|
|
|
|
|
|
|
} |
17
|
|
|
|
|
|
|
} |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
unless ($implementation) { |
20
|
|
|
|
|
|
|
require RedisDB::Parser::PP; |
21
|
|
|
|
|
|
|
$implementation = "RedisDB::Parser::PP"; |
22
|
|
|
|
|
|
|
} |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 NAME |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
RedisDB::Parse::Redis - redis protocol parser for RedisDB |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=head1 SYNOPSIS |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
use RedisDB::Parser; |
31
|
|
|
|
|
|
|
my $parser = RedisDB::Parser->new( master => $ref ); |
32
|
|
|
|
|
|
|
$parser->push_callback(\&cb); |
33
|
|
|
|
|
|
|
$parser->parse($data); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=head1 DESCRIPTION |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
This module provides methods to build redis requests and parse replies from |
38
|
|
|
|
|
|
|
the server. |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=head1 METHODS |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=head2 $class->new(%params) |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
Creates new parser object. Following parameters may be specified: |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=over 4 |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
=item B |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
Arbitrary reference. It is passed to callbacks as the first argument. Normally |
51
|
|
|
|
|
|
|
it would be a reference to the object managing connection to redis-server. |
52
|
|
|
|
|
|
|
Reference is weakened. |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=item B |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
Module allows you to set a separate callback for every new message. If there |
57
|
|
|
|
|
|
|
are no callbacks in queue, default_callback will be used. |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
=item B |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
If this parameter is set all data will be encoded as UTF-8 when building |
62
|
|
|
|
|
|
|
requests, and decoded from UTF-8 when parsing replies. By default module |
63
|
|
|
|
|
|
|
expects all data to be octet sequences. |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
=item B |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
If parsed message is an error message, parser will create object of the |
68
|
|
|
|
|
|
|
specified class with the message as the only constructor argument, and pass |
69
|
|
|
|
|
|
|
this object to the callback. By default L class is |
70
|
|
|
|
|
|
|
used. |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
=back |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=cut |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub new { |
77
|
1
|
|
|
1
|
1
|
2106
|
shift; |
78
|
1
|
|
|
|
|
9
|
return $implementation->new(@_); |
79
|
|
|
|
|
|
|
} |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
=head2 $class->implementation |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
Returns name of the package that actually implements parser functionality. It |
84
|
|
|
|
|
|
|
may be either L or L. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=cut |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
sub implementation { |
89
|
2
|
|
|
2
|
1
|
2064
|
return $implementation; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
=head2 $self->build_request($command, @arguments) |
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
Encodes I<$command> and I<@arguments> as redis request. |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
=head2 $self->push_callback(\&cb) |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
Pushes callback to the queue of callbacks. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
=head2 $self->set_default_callback(\&cb) |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
Set callback to invoke when there are no callbacks in queue. |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
=head2 $self->callbacks |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
Returns true if there are callbacks in queue |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
=head2 $self->propagate_reply($reply) |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
Invoke every callback from queue and the default callback with the given |
111
|
|
|
|
|
|
|
I<$reply>. Can be used e.g. if connection to server has been lost to invoke |
112
|
|
|
|
|
|
|
every callback with error message. |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
=head2 $self->parse($data) |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
Process new data received from the server. For every new reply method will |
117
|
|
|
|
|
|
|
invoke callback, either the one from the queue that was added using |
118
|
|
|
|
|
|
|
I method, or default callback if the queue is empty. Callback |
119
|
|
|
|
|
|
|
passed two arguments: master value, and decoded reply from the server. |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
=cut |
122
|
|
|
|
|
|
|
|
123
|
|
|
|
|
|
|
=head1 PARSING |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
Here's how the parser represents replies from redis-server: |
126
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
=head2 Status reply |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
Status replies are represented by string values without the initial plus sign |
130
|
|
|
|
|
|
|
and final end of the line symbols. I.e. "+OK" reply from the server will be |
131
|
|
|
|
|
|
|
parsed into "OK" string that will be passed to callback. |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head2 Error reply |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
Error replies are represents as objects of I, which is by default |
136
|
|
|
|
|
|
|
L. If parser detects error reply, it strips it off |
137
|
|
|
|
|
|
|
initial minus sign and final end of the line, and then passes result as sole |
138
|
|
|
|
|
|
|
argument to the I method of the I. This is the only case when |
139
|
|
|
|
|
|
|
parser produces blessed reference, and so callback may easily detect error |
140
|
|
|
|
|
|
|
condition by checking this. |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
=head2 Integer reply |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
Parser represents integer reply as a scalar value |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
=head2 Bulk reply |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
Parser represents bulk replies as scalar values. By default it treats result as |
149
|
|
|
|
|
|
|
a sequence of bytes, but if I options is set it decodes result from UTF-8 |
150
|
|
|
|
|
|
|
and may croak if result is not a valid UTF-8 sequence. NULL bulk reply is |
151
|
|
|
|
|
|
|
represented as undefined value. |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
=head2 Multi-bulk reply |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
Multi-bulk replies are returned as array references. Empty multi-bulk reply is |
156
|
|
|
|
|
|
|
represented as reference to empty array. Null multi-bulk reply is represented |
157
|
|
|
|
|
|
|
as undefined scalar. |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
=cut |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
1; |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
__END__ |