annotate lib/Cache/Memcached/GetParser.pm @ 0:17fc6afc155e CACHE_MEMCACHED_1_24

Cache::Memcached 1.24
author Maxim Dounin <mdounin@mdounin.ru>
date Sun, 30 Sep 2007 16:23:31 +0400
parents
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
1 package Cache::Memcached::GetParser;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
2 use strict;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
3 use warnings;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
4 use integer;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
5
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
6 use Errno qw( EINPROGRESS EWOULDBLOCK EISCONN );
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
7
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
8 use constant DEST => 0; # destination hashref we're writing into
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
9 use constant NSLEN => 1; # length of namespace to ignore on keys
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
10 use constant ON_ITEM => 2;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
11 use constant BUF => 3; # read buffer
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
12 use constant STATE => 4; # 0 = waiting for a line, N = reading N bytes
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
13 use constant OFFSET => 5; # offsets to read into buffers
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
14 use constant FLAGS => 6;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
15 use constant KEY => 7; # current key we're parsing (without the namespace prefix)
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
16
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
17 sub new {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
18 my ($class, $dest, $nslen, $on_item) = @_;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
19 return bless [$dest, $nslen, $on_item, '', 0, 0], $class;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
20 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
21
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
22 sub current_key {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
23 return $_[0][KEY];
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
24 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
25
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
26 # returns 1 on success, -1 on failure, and 0 if still working.
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
27 sub parse_from_sock {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
28 my ($self, $sock) = @_;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
29 my $res;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
30
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
31 # where are we reading into?
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
32 if ($self->[STATE]) { # reading value into $ret
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
33 my $ret = $self->[DEST];
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
34 $res = sysread($sock, $ret->{$self->[KEY]},
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
35 $self->[STATE] - $self->[OFFSET],
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
36 $self->[OFFSET]);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
37
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
38 return 0
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
39 if !defined($res) and $!==EWOULDBLOCK;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
40
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
41 if ($res == 0) { # catches 0=conn closed or undef=error
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
42 $self->[ON_ITEM] = undef;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
43 return -1;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
44 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
45
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
46 $self->[OFFSET] += $res;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
47 if ($self->[OFFSET] == $self->[STATE]) { # finished reading
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
48 $self->[ON_ITEM]->($self->[KEY], $self->[FLAGS]);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
49 $self->[OFFSET] = 0;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
50 $self->[STATE] = 0;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
51 # wait for another VALUE line or END...
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
52 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
53 return 0; # still working, haven't got to end yet
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
54 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
55
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
56 # we're reading a single line.
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
57 # first, read whatever's there, but be satisfied with 2048 bytes
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
58 $res = sysread($sock, $self->[BUF],
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
59 128*1024, $self->[OFFSET]);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
60 return 0
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
61 if !defined($res) and $!==EWOULDBLOCK;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
62 if ($res == 0) {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
63 $self->[ON_ITEM] = undef;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
64 return -1;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
65 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
66
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
67 $self->[OFFSET] += $res;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
68
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
69 return $self->parse_buffer;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
70 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
71
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
72 # returns 1 on success, -1 on failure, and 0 if still working.
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
73 sub parse_buffer {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
74 my ($self) = @_;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
75 my $ret = $self->[DEST];
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
76
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
77 SEARCH:
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
78 while (1) { # may have to search many times
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
79
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
80 # do we have a complete END line?
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
81 if ($self->[BUF] =~ /^END\r\n/) {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
82 $self->[ON_ITEM] = undef;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
83 return 1; # we're done successfully, return 1 to finish
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
84 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
85
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
86 # do we have a complete VALUE line?
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
87 if ($self->[BUF] =~ /^VALUE (\S+) (\d+) (\d+)\r\n/) {
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
88 ($self->[KEY], $self->[FLAGS], $self->[STATE]) =
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
89 (substr($1, $self->[NSLEN]), int($2), $3+2);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
90 # Note: we use $+[0] and not pos($self->[BUF]) because pos()
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
91 # seems to have problems under perl's taint mode. nobody
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
92 # on the list discovered why, but this seems a reasonable
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
93 # work-around:
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
94 my $p = $+[0];
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
95 my $len = length($self->[BUF]);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
96 my $copy = $len-$p > $self->[STATE] ? $self->[STATE] : $len-$p;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
97 $ret->{$self->[KEY]} = substr($self->[BUF], $p, $copy)
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
98 if $copy;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
99 $self->[OFFSET] = $copy;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
100 substr($self->[BUF], 0, $p+$copy, ''); # delete the stuff we used
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
101
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
102 if ($self->[OFFSET] == $self->[STATE]) { # have it all?
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
103 $self->[ON_ITEM]->($self->[KEY], $self->[FLAGS]);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
104 $self->[OFFSET] = 0;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
105 $self->[STATE] = 0;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
106 next SEARCH; # look again
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
107 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
108
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
109 last SEARCH; # buffer is empty now
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
110 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
111
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
112 # if we're here probably means we only have a partial VALUE
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
113 # or END line in the buffer. Could happen with multi-get,
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
114 # though probably very rarely. Exit the loop and let it read
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
115 # more.
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
116
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
117 # but first, make sure subsequent reads don't destroy our
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
118 # partial VALUE/END line.
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
119 $self->[OFFSET] = length($self->[BUF]);
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
120 last SEARCH;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
121 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
122 return 0;
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
123 }
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
124
17fc6afc155e Cache::Memcached 1.24
Maxim Dounin <mdounin@mdounin.ru>
parents:
diff changeset
125 1;