ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-FCP/FCP.pm
(Generate patch)

Comparing AnyEvent-FCP/FCP.pm (file contents):
Revision 1.17 by root, Sat Sep 5 19:36:12 2015 UTC vs.
Revision 1.24 by root, Sun Jun 12 04:44:05 2016 UTC

61 61
62use common::sense; 62use common::sense;
63 63
64use Carp; 64use Carp;
65 65
66our $VERSION = '0.3'; 66our $VERSION = 0.5;
67 67
68use Scalar::Util (); 68use Scalar::Util ();
69 69
70use AnyEvent; 70use AnyEvent;
71use AnyEvent::Handle; 71use AnyEvent::Handle;
86 1 while s/([^_])(SVK|CHK|URI|FCP|DS|MIME|DDA)/$1\_$2/; 86 1 while s/([^_])(SVK|CHK|URI|FCP|DS|MIME|DDA)/$1\_$2/;
87 s/(?<=[a-z])(?=[A-Z])/_/g; 87 s/(?<=[a-z])(?=[A-Z])/_/g;
88 lc 88 lc
89} 89}
90 90
91=item $fcp = new AnyEvent::FCP [host => $host][, port => $port][, name => $name] 91=item $fcp = new AnyEvent::FCP key => value...;
92 92
93Create a new FCP connection to the given host and port (default 93Create a new FCP connection to the given host and port (default
94127.0.0.1:9481, or the environment variables C<FREDHOST> and C<FREDPORT>). 94127.0.0.1:9481, or the environment variables C<FREDHOST> and C<FREDPORT>).
95 95
96If no C<name> was specified, then AnyEvent::FCP will generate a 96If no C<name> was specified, then AnyEvent::FCP will generate a
97(hopefully) unique client name for you. 97(hopefully) unique client name for you.
98
99The following keys can be specified (they are all optional):
100
101=over 4
102
103=item name => $string
104
105A unique name to identify this client. If none is specified, a randomly
106generated name will be used.
107
108=item host => $hostname
109
110The hostname or IP address of the freenet node. Default is C<$ENV{FREDHOST}>
111or C<127.0.0.1>.
112
113=item port => $portnumber
114
115The port number of the FCP port. Default is C<$ENV{FREDPORT}> or C<9481>.
116
117=item timeout => $seconds
118
119The timeout, in seconds, after which a connection error is assumed when
120there is no activity. Default is C<7200>, i.e. two hours.
121
122=item keepalive => $seconds
123
124The interval, in seconds, at which keepalive messages will be
125sent. Default is C<540>, i.e. nine minutes.
126
127These keepalive messages are useful both to detect that a connection is
128no longer working and to keep any (home) routers from expiring their
129masquerading entry.
130
131=item on_eof => $callback->($fcp)
132
133Invoked when the underlying L<AnyEvent::Handle> signals EOF, currently
134regardless of whether the EOF was expected or not.
135
136=item on_error => $callback->($fcp, $message)
137
138Invoked on any (fatal) errors, such as unexpected connection close. The
139callback receives the FCP object and a textual error message.
140
141=item on_failure => $callback->($fcp, $type, $backtrace, $args, $error)
142
143Invoked when an FCP request fails that didn't have a failure callback. See
144L<FCP REQUESTS> for details.
145
146=back
98 147
99=cut 148=cut
100 149
101sub new { 150sub new {
102 my $class = shift; 151 my $class = shift;
105 154
106 my $self = bless { 155 my $self = bless {
107 host => $ENV{FREDHOST} || "127.0.0.1", 156 host => $ENV{FREDHOST} || "127.0.0.1",
108 port => $ENV{FREDPORT} || 9481, 157 port => $ENV{FREDPORT} || 9481,
109 timeout => 3600 * 2, 158 timeout => 3600 * 2,
159 keepalive => 9 * 60,
110 name => time.rand.rand.rand, # lame 160 name => time.rand.rand.rand, # lame
111 @_, 161 @_,
112 queue => [], 162 queue => [],
113 req => {}, 163 req => {},
114 prefix => "..:aefcpid:$rand:", 164 prefix => "..:aefcpid:$rand:",
116 }, $class; 166 }, $class;
117 167
118 { 168 {
119 Scalar::Util::weaken (my $self = $self); 169 Scalar::Util::weaken (my $self = $self);
120 170
171 $self->{kw} = AE::timer $self->{keepalive}, $self->{keepalive}, sub {
172 $self->{hdl}->push_write ("\n");
173 };
174
121 our $ENDMESSAGE = qr<\012(EndMessage|Data)\012>; 175 our $ENDMESSAGE = qr<\012(EndMessage|Data)\012>;
122 176
123 # these are declared here for performance reasons 177 # these are declared here for performance reasons
124 my ($k, $v, $type); 178 my ($k, $v, $type);
125 my $rdata; 179 my $rdata;
130 # we only carve out whole messages here 184 # we only carve out whole messages here
131 while ($hdl->{rbuf} =~ /\012(EndMessage|Data)\012/) { 185 while ($hdl->{rbuf} =~ /\012(EndMessage|Data)\012/) {
132 # remember end marker 186 # remember end marker
133 $rdata = $1 eq "Data" 187 $rdata = $1 eq "Data"
134 or $1 eq "EndMessage" 188 or $1 eq "EndMessage"
135 or die "protocol error, expected message end, got $1\n"; 189 or return $self->fatal ("protocol error, expected message end, got $1\n");
136 190
137 my @lines = split /\012/, substr $hdl->{rbuf}, 0, $-[0]; 191 my @lines = split /\012/, substr $hdl->{rbuf}, 0, $-[0];
138 192
139 substr $hdl->{rbuf}, 0, $+[0], ""; # remove pkg 193 substr $hdl->{rbuf}, 0, $+[0], ""; # remove pkg
140 194
184 }; 238 };
185 239
186 $self->{hdl} = new AnyEvent::Handle 240 $self->{hdl} = new AnyEvent::Handle
187 connect => [$self->{host} => $self->{port}], 241 connect => [$self->{host} => $self->{port}],
188 timeout => $self->{timeout}, 242 timeout => $self->{timeout},
243 on_read => $on_read,
244 on_eof => sub {
245 if ($self->{on_eof}) {
246 $self->{on_eof}($self);
247 } else {
248 $self->fatal ("EOF");
249 }
250 },
189 on_error => sub { 251 on_error => sub {
190 warn "@_\n";#d# 252 $self->fatal ($_[2]);
191 exit 1;
192 }, 253 },
193 on_read => $on_read,
194 on_eof => $self->{on_eof} || sub { },
195 ; 254 ;
196 255
197 Scalar::Util::weaken ($self->{hdl}{fcp} = $self); 256 Scalar::Util::weaken ($self->{hdl}{fcp} = $self);
198 } 257 }
199 258
201 name => $self->{name}, 260 name => $self->{name},
202 expected_version => "2.0", 261 expected_version => "2.0",
203 ); 262 );
204 263
205 $self 264 $self
265}
266
267sub fatal {
268 my ($self, $msg) = @_;
269
270 $self->{hdl}->shutdown;
271 delete $self->{kw};
272
273 if ($self->{on_error}) {
274 $self->{on_error}->($self, $msg);
275 } else {
276 die $msg;
277 }
206} 278}
207 279
208sub identifier { 280sub identifier {
209 $_[0]{prefix} . ++$_[0]{idseq} 281 $_[0]{prefix} . ++$_[0]{idseq}
210} 282}
353 425
354Also comes in this underscore variant: 426Also comes in this underscore variant:
355 427
356 $fcp->get_plugin_info_ ($name, $detailed, $cb); 428 $fcp->get_plugin_info_ ($name, $detailed, $cb);
357 429
358You can thinbk of the underscore as a kind of continuation indicator - the 430You can think of the underscore as a kind of continuation indicator - the
359normal function waits and returns with the data, the C<_> indicates that 431normal function waits and returns with the data, the C<_> indicates that
360you pass the continuation yourself, and the continuation will be invoked 432you pass the continuation yourself, and the continuation will be invoked
361with the results. 433with the results.
362 434
363This callback/continuation argument (C<$cb>) can come in three forms itself: 435This callback/continuation argument (C<$cb>) can come in three forms itself:
365=over 4 437=over 4
366 438
367=item A code reference (or rather anything not matching some other alternative) 439=item A code reference (or rather anything not matching some other alternative)
368 440
369This code reference will be invoked with the result on success. On an 441This code reference will be invoked with the result on success. On an
442error, it will invoke the C<on_failure> callback of the FCP object, or,
370error, it will die (in the event loop) with a backtrace of the call site. 443if none was defined, will die (in the event loop) with a backtrace of the
444call site.
371 445
372This is a popular choice, but it makes handling errors hard - make sure 446This is a popular choice, but it makes handling errors hard - make sure
373you never generate protocol errors! 447you never generate protocol errors!
448
449In the failure case, if an C<on_failure> hook exists, it will be invoked
450with the FCP object, the request type (the name of the method), a
451(textual) backtrace as generated by C<Carp::longmess>, and arrayref
452containing the arguments from the original request invocation and the
453error object from the server, in this order, e.g.:
454
455 on_failure => sub {
456 my ($fcp, $request_type, $backtrace, $orig_args, $error_object) = @_;
457
458 warn "FCP failure ($type), $error_object->{code_description} ($error_object->{extra_description})$backtrace";
459 exit 1;
460 },
374 461
375=item A condvar (as returned by e.g. C<< AnyEvent->condvar >>) 462=item A condvar (as returned by e.g. C<< AnyEvent->condvar >>)
376 463
377When a condvar is passed, it is sent (C<< $cv->send ($results) >>) the 464When a condvar is passed, it is sent (C<< $cv->send ($results) >>) the
378results when the request has finished. Should an error occur, the error 465results when the request has finished. Should an error occur, the error
383=item An array with two callbacks C<[$success, $failure]> 470=item An array with two callbacks C<[$success, $failure]>
384 471
385The C<$success> callback will be invoked with the results, while the 472The C<$success> callback will be invoked with the results, while the
386C<$failure> callback will be invoked on any errors. 473C<$failure> callback will be invoked on any errors.
387 474
475The C<$failure> callback will be invoked with the error object from the
476server.
477
388=item C<undef> 478=item C<undef>
389 479
390This is the same thing as specifying C<sub { }> as callback, i.e. on 480This is the same thing as specifying C<sub { }> as callback, i.e. on
391success, the results are ignored, while on failure, you the module dies 481success, the results are ignored, while on failure, the C<on_failure> hook
392with a backtrace. 482is invoked or the module dies with a backtrace.
393 483
394This is good for quick scripts, or when you really aren't interested in 484This is good for quick scripts, or when you really aren't interested in
395the results. 485the results.
396 486
397=back 487=back
417 if (ARRAY:: eq ref $ok) { 507 if (ARRAY:: eq ref $ok) {
418 ($ok, $err) = @$ok; 508 ($ok, $err) = @$ok;
419 } elsif (UNIVERSAL::isa $ok, AnyEvent::CondVar::) { 509 } elsif (UNIVERSAL::isa $ok, AnyEvent::CondVar::) {
420 $err = sub { $ok->croak ($_[0]{extra_description}) }; 510 $err = sub { $ok->croak ($_[0]{extra_description}) };
421 } else { 511 } else {
422 my $bt = Carp::longmess ""; 512 my $bt = Carp::longmess "AnyEvent::FCP request $name";
513 Scalar::Util::weaken (my $self = $_[0]);
514 my $args = [@_]; shift @$args;
423 $err = sub { 515 $err = sub {
516 if ($self->{on_failure}) {
517 $self->{on_failure}($self, $name, $args, $bt, $_[0]);
518 } else {
424 die "$_[0]{code_description} ($_[0]{extra_description})$bt"; 519 die "$_[0]{code_description} ($_[0]{extra_description})$bt";
520 }
425 }; 521 };
426 } 522 }
427 523
428 $ok ||= $NOP_CB; 524 $ok ||= $NOP_CB;
429 525
641 }); 737 });
642}; 738};
643 739
644=item $status = $fcp->remove_request ($identifier[, $global]) 740=item $status = $fcp->remove_request ($identifier[, $global])
645 741
646Remove the request with the given isdentifier. Returns true if successful, 742Remove the request with the given identifier. Returns true if successful,
647false on error. 743false on error.
648 744
649=cut 745=cut
650 746
651_txn remove_request => sub { 747_txn remove_request => sub {
696 792
697C<$want_read> and C<$want_write> should be set to a true value when you 793C<$want_read> and C<$want_write> should be set to a true value when you
698want to read (get) files or write (put) files, respectively. 794want to read (get) files or write (put) files, respectively.
699 795
700On error, an exception is thrown. Otherwise, C<$can_read> and 796On error, an exception is thrown. Otherwise, C<$can_read> and
701C<$can_write> indicate whether you can reaqd or write to freenet via the 797C<$can_write> indicate whether you can read or write to freenet via the
702directory. 798directory.
703 799
704=cut 800=cut
705 801
706_txn test_dda => sub { 802_txn test_dda => sub {
827on every change, which will be called as C<< $cb->($fcp, $kv, $type) >>, where C<$type> 923on every change, which will be called as C<< $cb->($fcp, $kv, $type) >>, where C<$type>
828is the type of the original message triggering the change, 924is the type of the original message triggering the change,
829 925
830To fill this cache with the global queue and keep it updated, 926To fill this cache with the global queue and keep it updated,
831call C<watch_global> to subscribe to updates, followed by 927call C<watch_global> to subscribe to updates, followed by
832C<list_persistent_requests_sync>. 928C<list_persistent_requests>.
833 929
834 $fcp->watch_global_sync_; # do not wait 930 $fcp->watch_global_; # do not wait
835 $fcp->list_persistent_requests; # wait 931 $fcp->list_persistent_requests; # wait
836 932
837To get a better idea of what is stored in the cache, here is an example of 933To get a better idea of what is stored in the cache, here is an example of
838what might be stored in C<< $fcp->{req}{"Frost-gpl.txt"} >>: 934what might be stored in C<< $fcp->{req}{"Frost-gpl.txt"} >>:
839 935
948 if 0.1 > rand; 1044 if 0.1 > rand;
949 } 1045 }
950 } 1046 }
951 1047
952 # see if the dummy plugin is loaded, to ensure all previous requests have finished. 1048 # see if the dummy plugin is loaded, to ensure all previous requests have finished.
953 $fcp->get_plugin_info_sync ("dummy"); 1049 $fcp->get_plugin_info ("dummy");
954 1050
955=head1 SEE ALSO 1051=head1 SEE ALSO
956 1052
957L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0>, L<Net::FCP>. 1053L<http://wiki.freenetproject.org/FreenetFCPSpec2Point0>, L<Net::FCP>.
958 1054

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines