| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
#! /usr/bin/perl |
|
2
|
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
package Cache::Memcached::Queue; |
|
4
|
1
|
|
|
1
|
|
14642
|
use Moose; |
|
|
1
|
|
|
|
|
308530
|
|
|
|
1
|
|
|
|
|
6
|
|
|
5
|
1
|
|
|
1
|
|
4895
|
use Carp qw/confess cluck/; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
97
|
|
|
6
|
1
|
|
|
1
|
|
7
|
use feature qw/say switch/; |
|
|
1
|
|
|
|
|
7
|
|
|
|
1
|
|
|
|
|
107
|
|
|
7
|
1
|
|
|
1
|
|
793
|
use Cache::Memcached::Fast; |
|
|
1
|
|
|
|
|
4226
|
|
|
|
1
|
|
|
|
|
27
|
|
|
8
|
1
|
|
|
1
|
|
459
|
use Data::Serializer; |
|
|
1
|
|
|
|
|
1980
|
|
|
|
1
|
|
|
|
|
24
|
|
|
9
|
1
|
|
|
1
|
|
529
|
use Data::Dumper; |
|
|
1
|
|
|
|
|
4898
|
|
|
|
1
|
|
|
|
|
84
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
BEGIN { |
|
12
|
1
|
|
|
1
|
|
1915
|
our $VERSION = '0.1.8'; |
|
13
|
|
|
|
|
|
|
} |
|
14
|
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
has config_file => ( is => 'rw' ); |
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
has memcached => ( is => 'rw' ); |
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
has 'last' => ( is => 'rw' ); |
|
20
|
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
has first => ( is => 'rw' ); |
|
22
|
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
has memcached_servers => ( |
|
24
|
|
|
|
|
|
|
is => 'rw', |
|
25
|
|
|
|
|
|
|
isa => 'Cache::Memcached' |
|
26
|
|
|
|
|
|
|
); |
|
27
|
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
has name => ( is => 'rw', |
|
29
|
|
|
|
|
|
|
isa => 'Str', |
|
30
|
|
|
|
|
|
|
default => 'CMQID' ); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
has id => ( |
|
33
|
|
|
|
|
|
|
is => 'rw', |
|
34
|
|
|
|
|
|
|
required => 'id' |
|
35
|
|
|
|
|
|
|
); |
|
36
|
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
has qid => ( |
|
39
|
|
|
|
|
|
|
is => 'rw', |
|
40
|
|
|
|
|
|
|
isa => 'Str', |
|
41
|
|
|
|
|
|
|
); |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
has max_enq => ( |
|
44
|
|
|
|
|
|
|
is => 'rw', |
|
45
|
|
|
|
|
|
|
default => 0, |
|
46
|
|
|
|
|
|
|
); |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
has servers => ( |
|
49
|
|
|
|
|
|
|
is => 'rw', |
|
50
|
|
|
|
|
|
|
default => sub { return ['localhost:11211'] }, |
|
51
|
|
|
|
|
|
|
); |
|
52
|
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
has size => ( is => 'rw' ); |
|
54
|
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
has serialize => ( |
|
56
|
|
|
|
|
|
|
is => 'rw', |
|
57
|
|
|
|
|
|
|
isa => 'Int', |
|
58
|
|
|
|
|
|
|
default => 0, |
|
59
|
|
|
|
|
|
|
); |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
has serializer => ( |
|
62
|
|
|
|
|
|
|
is => 'rw', |
|
63
|
|
|
|
|
|
|
default => sub { |
|
64
|
|
|
|
|
|
|
return Data::Serializer->new( |
|
65
|
|
|
|
|
|
|
serializer => 'Storable', |
|
66
|
|
|
|
|
|
|
compress => 1, |
|
67
|
|
|
|
|
|
|
); |
|
68
|
|
|
|
|
|
|
} |
|
69
|
|
|
|
|
|
|
); |
|
70
|
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub BUILD { |
|
80
|
0
|
|
|
0
|
0
|
|
my ( $self, ) = @_; |
|
81
|
0
|
0
|
|
|
|
|
$self->memcached( |
|
82
|
|
|
|
|
|
|
Cache::Memcached::Fast->new( { servers => $self->servers } ) ) |
|
83
|
|
|
|
|
|
|
or confess "Can't load from memcached!"; |
|
84
|
0
|
|
|
|
|
|
my $name = $self->name; |
|
85
|
0
|
0
|
|
|
|
|
$name .= '_' if $name !~ /\_$/; |
|
86
|
0
|
|
|
|
|
|
$self->qid($name . $self->id); |
|
87
|
0
|
|
|
|
|
|
undef $name; |
|
88
|
0
|
|
|
|
|
|
$self->load; |
|
89
|
0
|
|
|
|
|
|
return $self; |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
sub load { |
|
100
|
0
|
|
|
0
|
1
|
|
my ($self,$flag) = @_; |
|
101
|
0
|
0
|
|
|
|
|
$flag = 0 if !defined($flag); |
|
102
|
0
|
|
|
|
|
|
my ( $ok, $id ) = ( 0, $self->id ); |
|
103
|
0
|
0
|
0
|
|
|
|
if ( !defined($id) || !$id ) { |
|
104
|
0
|
|
|
|
|
|
confess "You must define an id!"; |
|
105
|
|
|
|
|
|
|
} |
|
106
|
|
|
|
|
|
|
else { |
|
107
|
0
|
0
|
|
|
|
|
$id .= '_' if $id !~ /\_$/; |
|
108
|
0
|
|
|
|
|
|
my $qid = $self->name . '_' . $self->id . '_'; |
|
109
|
0
|
|
|
|
|
|
$self->qid($qid); |
|
110
|
0
|
|
|
|
|
|
my ( $first, $last, $size, $name ) = |
|
111
|
|
|
|
|
|
|
( $qid . 'first', $qid . 'last', $qid . 'size', $qid . 'name', ); |
|
112
|
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
#This queue already exists? |
|
114
|
0
|
|
|
|
|
|
my $real_first = $self->memcached->get($first); |
|
115
|
0
|
0
|
0
|
|
|
|
confess "Fatal error! Can't load or create queue! Check memcached server!" if $flag and !defined($real_first); |
|
116
|
0
|
0
|
|
|
|
|
if ( defined($real_first) ) { |
|
117
|
0
|
|
|
|
|
|
$self->first( $self->memcached->get($first) ); |
|
118
|
0
|
|
|
|
|
|
$self->last( $self->memcached->get($last) ); |
|
119
|
0
|
|
|
|
|
|
$self->size( $self->memcached->get($size) ); |
|
120
|
0
|
0
|
|
|
|
|
$self->name( $self->memcached->get($name) ) if !defined $self->name; |
|
121
|
0
|
|
|
|
|
|
$self->qid($qid); |
|
122
|
0
|
|
|
|
|
|
$ok = 1; |
|
123
|
|
|
|
|
|
|
} |
|
124
|
|
|
|
|
|
|
else { |
|
125
|
0
|
|
|
|
|
|
say q[Queue '] . $self->qid . q[' doesn't exists! Creating...]; |
|
126
|
0
|
|
|
|
|
|
$self->memcached->set($qid . 'LOCKED',$$,0); |
|
127
|
0
|
|
|
|
|
|
$self->memcached->set($name,$self->name,0); |
|
128
|
0
|
|
|
|
|
|
$self->memcached->set($first,$self->qid . '1',0,0); |
|
129
|
0
|
|
|
|
|
|
$self->memcached->set($last,$self->qid . '1',0,0); |
|
130
|
0
|
|
|
|
|
|
$self->memcached->set($size,0,0); |
|
131
|
0
|
|
|
|
|
|
$self->memcached->set($qid . 'LOCKED',0,0); |
|
132
|
0
|
|
|
|
|
|
say q[Queue '] . $self->qid . q[' was created!]; |
|
133
|
0
|
|
|
|
|
|
$self->load(1); |
|
134
|
|
|
|
|
|
|
} |
|
135
|
|
|
|
|
|
|
} |
|
136
|
0
|
|
|
|
|
|
return $ok; |
|
137
|
|
|
|
|
|
|
} |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub enq { |
|
147
|
0
|
|
|
0
|
1
|
|
my ( $self, $parameters ) = @_; |
|
148
|
0
|
|
|
|
|
|
my ( $ok, $expire, ) = ( 0, undef, undef ); |
|
149
|
0
|
0
|
|
|
|
|
if(!defined($parameters)){ |
|
150
|
0
|
|
|
|
|
|
say 'No value was defined to enqueue!'; |
|
151
|
|
|
|
|
|
|
} |
|
152
|
|
|
|
|
|
|
else { |
|
153
|
0
|
|
|
|
|
|
my $value = undef; |
|
154
|
0
|
0
|
|
|
|
|
if(ref($parameters) eq ''){ |
|
|
|
0
|
|
|
|
|
|
|
155
|
0
|
|
0
|
|
|
|
$value = $parameters // ''; |
|
156
|
|
|
|
|
|
|
} |
|
157
|
|
|
|
|
|
|
elsif(!defined($parameters->{value})){ |
|
158
|
0
|
|
0
|
|
|
|
$value = $parameters || ''; |
|
159
|
|
|
|
|
|
|
} |
|
160
|
|
|
|
|
|
|
else { |
|
161
|
0
|
|
0
|
|
|
|
$value = $parameters->{value} || ''; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
#checar se é necessário a serialização |
|
165
|
0
|
0
|
|
|
|
|
if(ref($value)){ |
|
166
|
|
|
|
|
|
|
#serializar |
|
167
|
0
|
|
|
|
|
|
my $serialized = $self->serializer->serialize($value); |
|
168
|
0
|
|
|
|
|
|
$value = $serialized; |
|
169
|
0
|
|
|
|
|
|
undef $serialized; |
|
170
|
|
|
|
|
|
|
} |
|
171
|
0
|
|
|
|
|
|
$self->load; |
|
172
|
0
|
0
|
0
|
|
|
|
if(!$self->_is_locked || $self->_unlock){ |
|
173
|
0
|
|
|
|
|
|
$self->_lock; |
|
174
|
0
|
|
0
|
|
|
|
my $size = $self->size // 0; |
|
175
|
|
|
|
|
|
|
#checando se a fila esta cheia |
|
176
|
0
|
0
|
0
|
|
|
|
if($self->max_enq > 0 && $self->size >= $self->max_enq){ |
|
177
|
0
|
|
|
|
|
|
say "Queue is full!"; |
|
178
|
|
|
|
|
|
|
} |
|
179
|
|
|
|
|
|
|
else { |
|
180
|
0
|
0
|
0
|
|
|
|
my $last = $1 if $self->last =~ /_(\d+)$/ // 1; |
|
181
|
|
|
|
|
|
|
#checando se last == first e se existe algum valor |
|
182
|
0
|
|
|
|
|
|
my $first_value = $self->memcached->get($self->first); |
|
183
|
0
|
0
|
|
|
|
|
if( $first_value) { |
|
184
|
0
|
|
|
|
|
|
$last++; |
|
185
|
|
|
|
|
|
|
} |
|
186
|
0
|
|
|
|
|
|
$size++; |
|
187
|
0
|
|
|
|
|
|
my $new_last = $self->qid . $last; |
|
188
|
0
|
|
|
|
|
|
$self->last($new_last); |
|
189
|
|
|
|
|
|
|
|
|
190
|
0
|
|
|
|
|
|
$self->memcached->set($new_last,$value,0); |
|
191
|
|
|
|
|
|
|
} |
|
192
|
0
|
|
|
|
|
|
$self->size($size); |
|
193
|
0
|
|
|
|
|
|
$self->_save(['last','size']); |
|
194
|
0
|
0
|
|
|
|
|
$self->_unlock if($self->_is_locked); |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
} |
|
197
|
0
|
|
|
|
|
|
return $ok; |
|
198
|
|
|
|
|
|
|
} |
|
199
|
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub deq { |
|
207
|
0
|
|
|
0
|
1
|
|
my ( $self, ) = @_; |
|
208
|
0
|
|
|
|
|
|
my ( $last_item,$value ) = ( undef,undef ); |
|
209
|
0
|
|
|
|
|
|
$self->load; |
|
210
|
0
|
0
|
0
|
|
|
|
if(!$self->_is_locked || $self->_unlock ){ |
|
211
|
0
|
|
|
|
|
|
$self->_lock; |
|
212
|
0
|
|
|
|
|
|
my $size = $self->size; |
|
213
|
0
|
0
|
|
|
|
|
if(!$size){ |
|
214
|
0
|
|
|
|
|
|
say 'Queue is empty!'; |
|
215
|
|
|
|
|
|
|
} |
|
216
|
|
|
|
|
|
|
else { |
|
217
|
0
|
0
|
0
|
|
|
|
my $first = $1 if $self->first =~ /_(\d+)$/ // 1; |
|
218
|
0
|
|
0
|
|
|
|
$value = $self->memcached->get($self->first) // ''; |
|
219
|
0
|
0
|
|
|
|
|
if($value =~ /^\^.*?Storable/i){ |
|
220
|
0
|
|
|
|
|
|
my $unserialized = $self->serializer->deserialize($value); |
|
221
|
0
|
|
|
|
|
|
$value = $unserialized; |
|
222
|
0
|
|
|
|
|
|
undef $unserialized; |
|
223
|
|
|
|
|
|
|
} |
|
224
|
0
|
|
|
|
|
|
$self->memcached->delete($self->first); |
|
225
|
0
|
0
|
|
|
|
|
if($self->last ne $self->first){ |
|
226
|
0
|
|
|
|
|
|
$first++; |
|
227
|
0
|
|
|
|
|
|
$self->first($self->qid . $first); |
|
228
|
0
|
0
|
|
|
|
|
$size-- if($size > 0); |
|
229
|
|
|
|
|
|
|
} |
|
230
|
|
|
|
|
|
|
else { |
|
231
|
0
|
|
|
|
|
|
$size = 0; |
|
232
|
0
|
|
|
|
|
|
$self->first($self->qid . '1',0); |
|
233
|
0
|
|
|
|
|
|
$self->last($self->qid . '1',0); |
|
234
|
0
|
|
|
|
|
|
$self->_save(['last']); |
|
235
|
|
|
|
|
|
|
} |
|
236
|
|
|
|
|
|
|
} |
|
237
|
0
|
|
|
|
|
|
$self->size($size); |
|
238
|
0
|
|
|
|
|
|
$self->_save(['first','size']); |
|
239
|
0
|
0
|
|
|
|
|
$self->_unlock if($self->_is_locked); |
|
240
|
|
|
|
|
|
|
} |
|
241
|
0
|
|
0
|
|
|
|
return $value // ''; |
|
242
|
|
|
|
|
|
|
} |
|
243
|
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
|
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
sub show { |
|
250
|
0
|
|
|
0
|
1
|
|
my ( $self, ) = @_; |
|
251
|
0
|
|
|
|
|
|
while(!$self->_lock){ |
|
252
|
0
|
|
|
|
|
|
$self->load; |
|
253
|
0
|
|
|
|
|
|
sleep .3; |
|
254
|
|
|
|
|
|
|
} |
|
255
|
0
|
0
|
0
|
|
|
|
my $first = $1 if $self->first =~ /_(\d+)$/ // 1; |
|
256
|
0
|
0
|
0
|
|
|
|
my $last = $1 if $self->last =~ /_(\d+)$/ // 1; |
|
257
|
0
|
|
|
|
|
|
foreach my $i($first..$last){ |
|
258
|
0
|
|
|
|
|
|
my $value = $self->memcached->get($self->qid . $i); |
|
259
|
0
|
|
|
|
|
|
say "$i - $value"; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
0
|
|
|
|
|
|
$self->_unlock; |
|
262
|
|
|
|
|
|
|
} |
|
263
|
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
sub cleanup { |
|
269
|
0
|
|
|
0
|
1
|
|
my ( $self, ) = @_; |
|
270
|
0
|
|
|
|
|
|
$self->load; |
|
271
|
|
|
|
|
|
|
$self->iterate(sub { |
|
272
|
0
|
|
|
0
|
|
|
my $index = shift; |
|
273
|
0
|
|
|
|
|
|
$self->memcached->delete($index); |
|
274
|
0
|
|
|
|
|
|
}); |
|
275
|
|
|
|
|
|
|
} |
|
276
|
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
sub _save { |
|
282
|
0
|
|
|
0
|
|
|
my ( $self, $parameters ) = @_; |
|
283
|
0
|
|
|
|
|
|
my $last = $self->last; |
|
284
|
0
|
|
|
|
|
|
my $ok = 0; |
|
285
|
|
|
|
|
|
|
|
|
286
|
0
|
0
|
|
|
|
|
if ( ref($parameters) !~ /ARRAY/ ) { |
|
287
|
0
|
|
|
|
|
|
confess "The parameters to save data MUST BE AN ARRAYREF"; |
|
288
|
|
|
|
|
|
|
} |
|
289
|
0
|
|
|
|
|
|
foreach my $k ( @{$parameters} ) { |
|
|
0
|
|
|
|
|
|
|
|
290
|
0
|
0
|
|
|
|
|
if ( $k !~ /^name|first|last|size|max_enq|qid$/ ) { |
|
291
|
0
|
|
|
|
|
|
confess "The parameter '$k' is invalid!"; |
|
292
|
|
|
|
|
|
|
} |
|
293
|
|
|
|
|
|
|
else { |
|
294
|
0
|
|
|
|
|
|
my $index = $self->qid . $k; |
|
295
|
0
|
0
|
|
|
|
|
if ( !$self->memcached->set( $index, $self->{$k},0 ) ) { |
|
296
|
0
|
|
|
|
|
|
confess "Memcached can't set a value!"; |
|
297
|
|
|
|
|
|
|
} |
|
298
|
|
|
|
|
|
|
else { |
|
299
|
0
|
|
|
|
|
|
$ok = 1; |
|
300
|
|
|
|
|
|
|
} |
|
301
|
|
|
|
|
|
|
} |
|
302
|
|
|
|
|
|
|
} |
|
303
|
0
|
|
|
|
|
|
return $ok; |
|
304
|
|
|
|
|
|
|
} |
|
305
|
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
sub iterate { |
|
311
|
0
|
|
|
0
|
1
|
|
my ( $self, $action, $action_params ) = @_; |
|
312
|
0
|
|
|
|
|
|
$self->load; |
|
313
|
0
|
0
|
0
|
|
|
|
if( (!defined($action) || !$action ) || |
|
|
|
0
|
0
|
|
|
|
|
|
|
|
0
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
314
|
|
|
|
|
|
|
(defined($action) && ref($action) !~ /CODE/) |
|
315
|
|
|
|
|
|
|
){ |
|
316
|
0
|
|
|
|
|
|
confess "'action' MUST be a CODE reference!"; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
elsif(defined($action_params) && ref($action_params) !~ /ARRAY/){ |
|
319
|
0
|
|
|
|
|
|
confess "'action_parameters' MUST be Array"; |
|
320
|
|
|
|
|
|
|
} |
|
321
|
|
|
|
|
|
|
elsif($self->size == 0){ |
|
322
|
0
|
|
|
|
|
|
say STDERR "Queue '" . $self->qid . "' is empty!"; |
|
323
|
|
|
|
|
|
|
} |
|
324
|
|
|
|
|
|
|
else { |
|
325
|
0
|
0
|
|
|
|
|
my $first_index = $1 if $self->first =~ /(\d+)$/; |
|
326
|
0
|
0
|
|
|
|
|
my $last_index = $1 if $self->last =~ /(\d+)$/; |
|
327
|
0
|
|
|
|
|
|
say "The queue is " . $self->name; |
|
328
|
0
|
|
|
|
|
|
foreach my $i($first_index .. $last_index){ |
|
329
|
|
|
|
|
|
|
#mounting index for memcached |
|
330
|
0
|
|
|
|
|
|
my $mc_index = $self->qid; |
|
331
|
0
|
0
|
|
|
|
|
$mc_index .= '_' if $mc_index !~ /_$/; |
|
332
|
0
|
|
|
|
|
|
$mc_index .= $i; |
|
333
|
0
|
|
|
|
|
|
my $value = $self->memcached->get($mc_index); |
|
334
|
0
|
0
|
|
|
|
|
if(!defined($value)){ |
|
335
|
0
|
|
|
|
|
|
confess "An error occured trying make a 'get' operation. No value found for '$mc_index' index"; |
|
336
|
|
|
|
|
|
|
} |
|
337
|
0
|
|
|
|
|
|
$action->($mc_index,$value,$action_params); |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
} |
|
340
|
|
|
|
|
|
|
} |
|
341
|
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
sub _lock { |
|
349
|
0
|
|
|
0
|
|
|
my ($self,$pid,$lock_pid) = (shift,$$,0); |
|
350
|
0
|
|
|
|
|
|
$self->load; |
|
351
|
0
|
|
|
|
|
|
my $qid = $self->qid; |
|
352
|
0
|
0
|
0
|
|
|
|
confess "Panic! No 'qid'!" if (!defined($qid) || !$qid); |
|
353
|
0
|
|
|
|
|
|
my $lock_idx = $qid . 'LOCKED'; |
|
354
|
0
|
|
|
|
|
|
$lock_pid = $self->_is_locked($lock_idx); |
|
355
|
0
|
0
|
|
|
|
|
if(!$lock_pid){ |
|
356
|
0
|
|
|
|
|
|
my $rs = $self->memcached->set($lock_idx,$pid,0); |
|
357
|
0
|
0
|
|
|
|
|
confess "Memcached server can't write!" if !defined($rs); |
|
358
|
0
|
|
|
|
|
|
$lock_pid = $pid; |
|
359
|
|
|
|
|
|
|
} |
|
360
|
|
|
|
|
|
|
else { |
|
361
|
0
|
|
|
|
|
|
say "is already locked!"; |
|
362
|
0
|
|
|
|
|
|
$lock_pid = 0; |
|
363
|
|
|
|
|
|
|
} |
|
364
|
0
|
|
|
|
|
|
$self->load; |
|
365
|
0
|
|
0
|
|
|
|
return $lock_pid || 0; |
|
366
|
|
|
|
|
|
|
} |
|
367
|
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
sub _unlock { |
|
374
|
0
|
|
|
0
|
|
|
my ($self,$pid,$ok) = (shift,$$,0); |
|
375
|
0
|
|
|
|
|
|
$self->load; |
|
376
|
0
|
|
|
|
|
|
my $qid = $self->qid; |
|
377
|
0
|
0
|
0
|
|
|
|
confess "Panic! No 'qid'!" if (!defined($qid) || !$qid); |
|
378
|
0
|
|
|
|
|
|
my $lock_idx = $qid . 'LOCKED'; |
|
379
|
0
|
|
|
|
|
|
my $lock_pid = $self->_is_locked($lock_idx); |
|
380
|
0
|
0
|
0
|
|
|
|
if($lock_pid && $lock_pid == $pid){ |
|
|
|
0
|
0
|
|
|
|
|
|
381
|
0
|
|
|
|
|
|
my $rs = $self->memcached->set($lock_idx,0,0); |
|
382
|
0
|
0
|
|
|
|
|
confess "Memcached can't write!" if !defined($rs); |
|
383
|
0
|
|
|
|
|
|
$ok = 1; |
|
384
|
|
|
|
|
|
|
} |
|
385
|
|
|
|
|
|
|
elsif($lock_pid && $lock_pid != $pid){ |
|
386
|
0
|
|
|
|
|
|
say "Is locked by another process! $lock_pid"; |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
} |
|
389
|
0
|
|
|
|
|
|
$self->load; |
|
390
|
0
|
|
|
|
|
|
return $ok; |
|
391
|
|
|
|
|
|
|
} |
|
392
|
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
sub _is_locked { |
|
399
|
0
|
|
|
0
|
|
|
my ($self,$lock_idx) = @_; |
|
400
|
0
|
0
|
|
|
|
|
$lock_idx = 0 if !defined $lock_idx; |
|
401
|
0
|
|
|
|
|
|
my $found = 0; |
|
402
|
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
# confess "Parameter 'lock_idx' is mandatory!" if (!defined($lock_idx) || !$lock_idx); |
|
404
|
0
|
0
|
0
|
|
|
|
if(!defined($lock_idx) || !$lock_idx){ |
|
405
|
0
|
|
|
|
|
|
$lock_idx = $self->qid . 'LOCKED'; |
|
406
|
|
|
|
|
|
|
} |
|
407
|
0
|
|
|
|
|
|
my $lock_pid = $self->memcached->get($lock_idx); #this pid locked the queue! |
|
408
|
|
|
|
|
|
|
# $lock_pid = 0 if $$ == $lock_pid; |
|
409
|
|
|
|
|
|
|
# foreach my $p(@{$t->table}){ |
|
410
|
|
|
|
|
|
|
# if($p->pid == $lock_pid){ |
|
411
|
|
|
|
|
|
|
# $found = $p->pid; |
|
412
|
|
|
|
|
|
|
# last; |
|
413
|
|
|
|
|
|
|
# } |
|
414
|
|
|
|
|
|
|
# } |
|
415
|
|
|
|
|
|
|
# $lock_pid = 0 if !$found; |
|
416
|
0
|
|
|
|
|
|
return $lock_pid ; |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
|
|
419
|
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
__PACKAGE__->meta->make_immutable; |
|
424
|
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
=head1 NAME |
|
426
|
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Cache::Memcached::Queue - Simple and elegant way to persist queues on Memcached |
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=head1 VERSION |
|
430
|
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
Version 0.1.8 |
|
432
|
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
unstable version |
|
434
|
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
=cut |
|
436
|
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=head1 DESCRIPTION |
|
438
|
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
The idea is take advantage from Cache::Memcached::Fast module using it as a back-end for |
|
440
|
|
|
|
|
|
|
queue structures without sockets, extra protocols or extra databases to maintain queues-metadata. |
|
441
|
|
|
|
|
|
|
All stuff is stored on Memcached! Including metadata. |
|
442
|
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
|
|
444
|
|
|
|
|
|
|
This can be done adding some metadata on Memcached hash structure that controls data on |
|
445
|
|
|
|
|
|
|
a queue structure(strict FIFO). This metadata defines identification for queues and |
|
446
|
|
|
|
|
|
|
controls first element, last element, size(number of elements) and lock information |
|
447
|
|
|
|
|
|
|
following patterns in their names. For stabilish this patterns, it's necessary to define |
|
448
|
|
|
|
|
|
|
some elements: |
|
449
|
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
=over |
|
451
|
|
|
|
|
|
|
|
|
452
|
|
|
|
|
|
|
=item * prefix - WARNING! This attribute is deprecated!!! DON'T USE IT! |
|
453
|
|
|
|
|
|
|
|
|
454
|
|
|
|
|
|
|
=item * index - WARNING! This attribute is deprecated! DON'T USE IT! |
|
455
|
|
|
|
|
|
|
|
|
456
|
|
|
|
|
|
|
=item * name - This is a 'string' that defines a name for your queue; |
|
457
|
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=item * id - It's a unique identifier for your queue and is defined on the 'id' attribute. |
|
459
|
|
|
|
|
|
|
You can have queues with the same name since you have different ids; |
|
460
|
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
|
|
462
|
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=back |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
=head1 SYNOPSIS |
|
468
|
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
use common::sense; |
|
470
|
|
|
|
|
|
|
use Cache::Memcached::Queue; |
|
471
|
|
|
|
|
|
|
my $q = Cache::Memcached::Queue->new( |
|
472
|
|
|
|
|
|
|
name => 'foo', |
|
473
|
|
|
|
|
|
|
id => 1, |
|
474
|
|
|
|
|
|
|
servers => ['localhost:11211'], #This is default. RTFM ON Cache::Memcached::Fast for more options |
|
475
|
|
|
|
|
|
|
serialize => 1, #if true, every value on enq will be serialized (Data::Serializer with Storable) |
|
476
|
|
|
|
|
|
|
#but if complex data is passed(hashes, arrays, objects, etc), this data will be |
|
477
|
|
|
|
|
|
|
#serialized even serialize attribute is false. |
|
478
|
|
|
|
|
|
|
); |
|
479
|
|
|
|
|
|
|
|
|
480
|
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
#loading queue |
|
482
|
|
|
|
|
|
|
$q->load();#load data from Memcached |
|
483
|
|
|
|
|
|
|
|
|
484
|
|
|
|
|
|
|
#common operations... |
|
485
|
|
|
|
|
|
|
$q->enq('fus'); #enqueue 'fus'. |
|
486
|
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
$q->enq('goh'); #enqueue 'goh' and this never expires on memcached |
|
488
|
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
$q->show; #show all items from queue. In this case: 'goh'. Remember... FIFO(First In First Out). |
|
490
|
|
|
|
|
|
|
|
|
491
|
|
|
|
|
|
|
$q->deq; #deqeue 'fus'. |
|
492
|
|
|
|
|
|
|
|
|
493
|
|
|
|
|
|
|
$q->show; #show all items from queue. In this case: 'nuke'(first and last element from queue). |
|
494
|
|
|
|
|
|
|
|
|
495
|
|
|
|
|
|
|
$q->enq({'fus'=>['goh','dah']}); #enqueue serialize and compact data. |
|
496
|
|
|
|
|
|
|
|
|
497
|
|
|
|
|
|
|
$q->cleanup; #cleans everything. From object and from Memcached. |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
=head2 load() |
|
502
|
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
Try to load the queue metadata from Memcached. If works, will return true. Otherwise |
|
504
|
|
|
|
|
|
|
will return false. |
|
505
|
|
|
|
|
|
|
|
|
506
|
|
|
|
|
|
|
|
|
507
|
|
|
|
|
|
|
=head2 enq( HashRef $parameters or SCALAR $value ) |
|
508
|
|
|
|
|
|
|
|
|
509
|
|
|
|
|
|
|
Try to make a 'enqueue' operation. You can enqueue scalar or complex data(hashes, arrays, objects etc). |
|
510
|
|
|
|
|
|
|
|
|
511
|
|
|
|
|
|
|
There is two ways to enqueue: |
|
512
|
|
|
|
|
|
|
|
|
513
|
|
|
|
|
|
|
=over |
|
514
|
|
|
|
|
|
|
|
|
515
|
|
|
|
|
|
|
=item * common way(RECOMMENDED): |
|
516
|
|
|
|
|
|
|
|
|
517
|
|
|
|
|
|
|
my $Bar = 'Bar'; |
|
518
|
|
|
|
|
|
|
my @Array = ('Foo','Bar'); |
|
519
|
|
|
|
|
|
|
my %Hash = ('Foo' => 'Bar'); |
|
520
|
|
|
|
|
|
|
$q->enq('Foo'); |
|
521
|
|
|
|
|
|
|
$q->enq($Bar); |
|
522
|
|
|
|
|
|
|
$q->enq(\@MyArray); |
|
523
|
|
|
|
|
|
|
$q->enq(\%MyHash); #since %MyHash doesn't have 'value' and/or 'serialize' as an hash key. This is not treated by module! |
|
524
|
|
|
|
|
|
|
$q->enq({ some => [{complex => 'data'}],}, |
|
525
|
|
|
|
|
|
|
); |
|
526
|
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
Hashes and Arrays must be passed as a reference! ALWAYS! |
|
528
|
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
=item * alternative way(NOT RECOMMENDED): |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
$q->enq({value => 'Foo'}); |
|
532
|
|
|
|
|
|
|
$q->enq({value => $Bar}); |
|
533
|
|
|
|
|
|
|
$q->enq({value => \@MyArray}); |
|
534
|
|
|
|
|
|
|
$q->enq({value => \%MyHash}); |
|
535
|
|
|
|
|
|
|
$q->enq({value => { some => [{complex => 'data'}],} ); |
|
536
|
|
|
|
|
|
|
|
|
537
|
|
|
|
|
|
|
=back |
|
538
|
|
|
|
|
|
|
|
|
539
|
|
|
|
|
|
|
If you try to enqueue complex data, it will be serialized. Doesn't matter if serialize attribute or |
|
540
|
|
|
|
|
|
|
parameter is set to false. |
|
541
|
|
|
|
|
|
|
|
|
542
|
|
|
|
|
|
|
If you want to use alternative way, you must know the following valid parameters: |
|
543
|
|
|
|
|
|
|
|
|
544
|
|
|
|
|
|
|
=over |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
=item value - A value that presupposes that you want to save |
|
547
|
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
=item serialize - If you need the value to be serialized, you must set serialized to true(1). |
|
549
|
|
|
|
|
|
|
|
|
550
|
|
|
|
|
|
|
=back |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
Example2: $enq({value => $some_object_or_structure, |
|
554
|
|
|
|
|
|
|
serialize => 1, }); |
|
555
|
|
|
|
|
|
|
|
|
556
|
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
If this work, the method will return true. Otherwise, will return false. |
|
558
|
|
|
|
|
|
|
|
|
559
|
|
|
|
|
|
|
You can change serialize parameters setting 'serializer' method too. |
|
560
|
|
|
|
|
|
|
|
|
561
|
|
|
|
|
|
|
|
|
562
|
|
|
|
|
|
|
|
|
563
|
|
|
|
|
|
|
=head2 deq() |
|
564
|
|
|
|
|
|
|
|
|
565
|
|
|
|
|
|
|
Try to make a 'dequeue' operation on Queue. That means the first value |
|
566
|
|
|
|
|
|
|
of queue will be removed from queue, and the first index pointer from queue will |
|
567
|
|
|
|
|
|
|
be moved to the next index. If works, returns the 'dequeued' |
|
568
|
|
|
|
|
|
|
value, otherwise returns undef. |
|
569
|
|
|
|
|
|
|
|
|
570
|
|
|
|
|
|
|
There is no parameters |
|
571
|
|
|
|
|
|
|
|
|
572
|
|
|
|
|
|
|
Example: |
|
573
|
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
my $first_element_of_queue = $q->deq; |
|
575
|
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
|
|
577
|
|
|
|
|
|
|
|
|
578
|
|
|
|
|
|
|
=head2 show() |
|
579
|
|
|
|
|
|
|
|
|
580
|
|
|
|
|
|
|
Try to show the content of queue(the data). This is made finding the 'first' |
|
581
|
|
|
|
|
|
|
and 'last' pointers, extracting the sequential index, and interate the queue |
|
582
|
|
|
|
|
|
|
with this indexes, making a 'get' operation from Memcached. If the value |
|
583
|
|
|
|
|
|
|
exists, it will be showed. If not, a exception will be thrown . |
|
584
|
|
|
|
|
|
|
|
|
585
|
|
|
|
|
|
|
There is no parameters |
|
586
|
|
|
|
|
|
|
|
|
587
|
|
|
|
|
|
|
Example: |
|
588
|
|
|
|
|
|
|
|
|
589
|
|
|
|
|
|
|
say $q->show; |
|
590
|
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
|
|
592
|
|
|
|
|
|
|
=head2 cleanup() |
|
593
|
|
|
|
|
|
|
|
|
594
|
|
|
|
|
|
|
Dequeue everything! No parameters! Returns true, if it's all right! Otherwise, returns false/throws an exception |
|
595
|
|
|
|
|
|
|
|
|
596
|
|
|
|
|
|
|
|
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
=head2 save( ArrayRef $parameters ) |
|
599
|
|
|
|
|
|
|
|
|
600
|
|
|
|
|
|
|
Internal method to save the queue metadata. |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
|
|
603
|
|
|
|
|
|
|
=head2 iterate(CODE $action, Array $action_params) |
|
604
|
|
|
|
|
|
|
|
|
605
|
|
|
|
|
|
|
That method is a 'handler'. You can treat all values in another subroutine/static method, passing |
|
606
|
|
|
|
|
|
|
two parameters: |
|
607
|
|
|
|
|
|
|
|
|
608
|
|
|
|
|
|
|
=over |
|
609
|
|
|
|
|
|
|
|
|
610
|
|
|
|
|
|
|
=item * action: this parameter MUST be a CODE reference. Example: |
|
611
|
|
|
|
|
|
|
|
|
612
|
|
|
|
|
|
|
#EX1: $q->iterate( |
|
613
|
|
|
|
|
|
|
sub { |
|
614
|
|
|
|
|
|
|
my ($index,$value,$params) = @_; |
|
615
|
|
|
|
|
|
|
#do something with this!!! |
|
616
|
|
|
|
|
|
|
} |
|
617
|
|
|
|
|
|
|
|
|
618
|
|
|
|
|
|
|
#EX2: $q->iterate( \&somesubroutine,$myparams) ; |
|
619
|
|
|
|
|
|
|
sub somesubroutine { |
|
620
|
|
|
|
|
|
|
my ($index,$value,$params) = @_; |
|
621
|
|
|
|
|
|
|
#do something cool! |
|
622
|
|
|
|
|
|
|
} |
|
623
|
|
|
|
|
|
|
|
|
624
|
|
|
|
|
|
|
=item * action_params: This can be a custom parameters. All yours! |
|
625
|
|
|
|
|
|
|
|
|
626
|
|
|
|
|
|
|
|
|
627
|
|
|
|
|
|
|
|
|
628
|
|
|
|
|
|
|
=back |
|
629
|
|
|
|
|
|
|
|
|
630
|
|
|
|
|
|
|
|
|
631
|
|
|
|
|
|
|
So, by default, every index and values that are in your queue are passed together with your customized parameters. |
|
632
|
|
|
|
|
|
|
|
|
633
|
|
|
|
|
|
|
If you pass everything right, your 'action' will be performed! Otherwise, an exception will be throwed. |
|
634
|
|
|
|
|
|
|
|
|
635
|
|
|
|
|
|
|
=cut |
|
636
|
|
|
|
|
|
|
|
|
637
|
|
|
|
|
|
|
=head1 AUTHOR |
|
638
|
|
|
|
|
|
|
|
|
639
|
|
|
|
|
|
|
Andre Garcia Carneiro, C<< <bang at cpan.org> >> |
|
640
|
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
=head1 BUGS |
|
642
|
|
|
|
|
|
|
|
|
643
|
|
|
|
|
|
|
The queue lost reference to last element when there is more than one process accessing queue. I'm working on it. |
|
644
|
|
|
|
|
|
|
|
|
645
|
|
|
|
|
|
|
Please report any bugs or feature requests to C<bug-cache-memcached-queue at rt.cpan.org>, or through |
|
646
|
|
|
|
|
|
|
the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Cache-memcached-Queue>. I will be notified, and then you'll |
|
647
|
|
|
|
|
|
|
automatically be notified of progress on your bug as I make changes. |
|
648
|
|
|
|
|
|
|
|
|
649
|
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
=head1 NOTES FOR THIS VERSION |
|
651
|
|
|
|
|
|
|
|
|
652
|
|
|
|
|
|
|
=over |
|
653
|
|
|
|
|
|
|
|
|
654
|
|
|
|
|
|
|
=item * 'beta' version was change to 'unstable', because multi-processing access is not working well yet. |
|
655
|
|
|
|
|
|
|
|
|
656
|
|
|
|
|
|
|
=item * The auto-installer was removed after CPAN request. |
|
657
|
|
|
|
|
|
|
|
|
658
|
|
|
|
|
|
|
=item * 'servers' attribute have ['localhost:11211'] as default value; |
|
659
|
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
=item * 'serialize' attribute is DEPRECATED. Doesn't work anymore; |
|
661
|
|
|
|
|
|
|
|
|
662
|
|
|
|
|
|
|
=item * The new method 'iterator' allows delegate to other subroutine/static method queue data; |
|
663
|
|
|
|
|
|
|
|
|
664
|
|
|
|
|
|
|
=item * 'lock' feature is a internal feature that allows have a same queue with multiple processes working on it. (EXPERIMENTAL) |
|
665
|
|
|
|
|
|
|
|
|
666
|
|
|
|
|
|
|
=item * 'init' method was removed! |
|
667
|
|
|
|
|
|
|
|
|
668
|
|
|
|
|
|
|
=back |
|
669
|
|
|
|
|
|
|
|
|
670
|
|
|
|
|
|
|
|
|
671
|
|
|
|
|
|
|
=head1 TODO |
|
672
|
|
|
|
|
|
|
|
|
673
|
|
|
|
|
|
|
=over |
|
674
|
|
|
|
|
|
|
|
|
675
|
|
|
|
|
|
|
=item * performance optimization |
|
676
|
|
|
|
|
|
|
|
|
677
|
|
|
|
|
|
|
=item * 'priority' support, maybe |
|
678
|
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
=back |
|
681
|
|
|
|
|
|
|
|
|
682
|
|
|
|
|
|
|
=head1 SUPPORT |
|
683
|
|
|
|
|
|
|
|
|
684
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
|
685
|
|
|
|
|
|
|
|
|
686
|
|
|
|
|
|
|
perldoc Cache::Memcached::Queue |
|
687
|
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
|
|
689
|
|
|
|
|
|
|
You can also look for information at: |
|
690
|
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
=over 4 |
|
692
|
|
|
|
|
|
|
|
|
693
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
|
694
|
|
|
|
|
|
|
|
|
695
|
|
|
|
|
|
|
L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Cache-memcached-Queue> |
|
696
|
|
|
|
|
|
|
|
|
697
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
|
698
|
|
|
|
|
|
|
|
|
699
|
|
|
|
|
|
|
L<http://annocpan.org/dist/Cache-memcached-Queue> |
|
700
|
|
|
|
|
|
|
|
|
701
|
|
|
|
|
|
|
=item * CPAN Ratings |
|
702
|
|
|
|
|
|
|
|
|
703
|
|
|
|
|
|
|
L<http://cpanratings.perl.org/d/Cache-memcached-Queue> |
|
704
|
|
|
|
|
|
|
|
|
705
|
|
|
|
|
|
|
=item * Search CPAN |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
L<http://search.cpan.org/dist/Cache-memcached-Queue/> |
|
708
|
|
|
|
|
|
|
|
|
709
|
|
|
|
|
|
|
=back |
|
710
|
|
|
|
|
|
|
|
|
711
|
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
|
|
713
|
|
|
|
|
|
|
=head1 LICENSE AND COPYRIGHT |
|
714
|
|
|
|
|
|
|
|
|
715
|
|
|
|
|
|
|
Copyright 2013 2014 Andre Garcia Carneiro. |
|
716
|
|
|
|
|
|
|
|
|
717
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify it |
|
718
|
|
|
|
|
|
|
under the terms of either: the GNU General Public License as published |
|
719
|
|
|
|
|
|
|
by the Free Software Foundation; or the Artistic License. |
|
720
|
|
|
|
|
|
|
|
|
721
|
|
|
|
|
|
|
See http://dev.perl.org/licenses/ for more information. |
|
722
|
|
|
|
|
|
|
|
|
723
|
|
|
|
|
|
|
|
|
724
|
|
|
|
|
|
|
=cut |
|
725
|
|
|
|
|
|
|
|
|
726
|
|
|
|
|
|
|
1; # End of Cache::Memcached::Queue |
|
727
|
|
|
|
|
|
|
|
|
728
|
|
|
|
|
|
|
## Please see file perltidy.ERR |