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

Comparing AnyEvent-MP/MP.pm (file contents):
Revision 1.31 by root, Wed Aug 5 19:55:58 2009 UTC vs.
Revision 1.35 by root, Thu Aug 6 10:21:48 2009 UTC

22 snd $port2, ping => $port1; 22 snd $port2, ping => $port1;
23 23
24 # more, smarter, matches (_any_ is exported by this module) 24 # more, smarter, matches (_any_ is exported by this module)
25 rcv $port, [child_died => $pid] => sub { ... 25 rcv $port, [child_died => $pid] => sub { ...
26 rcv $port, [_any_, _any_, 3] => sub { .. $_[2] is 3 26 rcv $port, [_any_, _any_, 3] => sub { .. $_[2] is 3
27
28 # linking two ports, so they both crash together
29 lnk $port1, $port2;
30
31 # monitoring
32 mon $port, $cb->(@msg) # callback is invoked on death
33 mon $port, $otherport # kill otherport on abnormal death
34 mon $port, $otherport, @msg # send message on death
27 35
28=head1 DESCRIPTION 36=head1 DESCRIPTION
29 37
30This module (-family) implements a simple message passing framework. 38This module (-family) implements a simple message passing framework.
31 39
123The C<NODE> function returns, and the C<$NODE> variable contains 131The C<NODE> function returns, and the C<$NODE> variable contains
124the noderef of the local node. The value is initialised by a call 132the noderef of the local node. The value is initialised by a call
125to C<become_public> or C<become_slave>, after which all local port 133to C<become_public> or C<become_slave>, after which all local port
126identifiers become invalid. 134identifiers become invalid.
127 135
128=item $noderef = node_of $portid 136=item $noderef = node_of $port
129 137
130Extracts and returns the noderef from a portid or a noderef. 138Extracts and returns the noderef from a portid or a noderef.
139
140=item initialise_node $noderef, $seednode, $seednode...
141
142=item initialise_node "slave/", $master, $master...
143
144Before a node can talk to other nodes on the network it has to initialise
145itself - the minimum a node needs to know is it's own name, and optionally
146it should know the noderefs of some other nodes in the network.
147
148This function initialises a node - it must be called exactly once (or
149never) before calling other AnyEvent::MP functions.
150
151All arguments are noderefs, which can be either resolved or unresolved.
152
153There are two types of networked nodes, public nodes and slave nodes:
154
155=over 4
156
157=item public nodes
158
159For public nodes, C<$noderef> must either be a (possibly unresolved)
160noderef, in which case it will be resolved, or C<undef> (or missing), in
161which case the noderef will be guessed.
162
163Afterwards, the node will bind itself on all endpoints and try to connect
164to all additional C<$seednodes> that are specified. Seednodes are optional
165and can be used to quickly bootstrap the node into an existing network.
166
167=item slave nodes
168
169When the C<$noderef> is the special string C<slave/>, then the node will
170become a slave node. Slave nodes cannot be contacted from outside and will
171route most of their traffic to the master node that they attach to.
172
173At least one additional noderef is required: The node will try to connect
174to all of them and will become a slave attached to the first node it can
175successfully connect to.
176
177=back
178
179This function will block until all nodes have been resolved and, for slave
180nodes, until it has successfully established a connection to a master
181server.
182
183Example: become a public node listening on the default node.
184
185 initialise_node;
186
187Example: become a public node, and try to contact some well-known master
188servers to become part of the network.
189
190 initialise_node undef, "master1", "master2";
191
192Example: become a public node listening on port C<4041>.
193
194 initialise_node 4041;
195
196Example: become a public node, only visible on localhost port 4044.
197
198 initialise_node "locahost:4044";
199
200Example: become a slave node to any of the specified master servers.
201
202 initialise_node "slave/", "master1", "192.168.13.17", "mp.example.net";
131 203
132=item $cv = resolve_node $noderef 204=item $cv = resolve_node $noderef
133 205
134Takes an unresolved node reference that may contain hostnames and 206Takes an unresolved node reference that may contain hostnames and
135abbreviated IDs, resolves all of them and returns a resolved node 207abbreviated IDs, resolves all of them and returns a resolved node
167 239
168Due to some quirks in how perl exports variables, it is impossible to 240Due to some quirks in how perl exports variables, it is impossible to
169just export C<$SELF>, all the symbols called C<SELF> are exported by this 241just export C<$SELF>, all the symbols called C<SELF> are exported by this
170module, but only C<$SELF> is currently used. 242module, but only C<$SELF> is currently used.
171 243
172=item snd $portid, type => @data 244=item snd $port, type => @data
173 245
174=item snd $portid, @msg 246=item snd $port, @msg
175 247
176Send the given message to the given port ID, which can identify either 248Send the given message to the given port ID, which can identify either
177a local or a remote port, and can be either a string or soemthignt hat 249a local or a remote port, and can be either a string or soemthignt hat
178stringifies a sa port ID (such as a port object :). 250stringifies a sa port ID (such as a port object :).
179 251
189JSON is used, then only strings, numbers and arrays and hashes consisting 261JSON is used, then only strings, numbers and arrays and hashes consisting
190of those are allowed (no objects). When Storable is used, then anything 262of those are allowed (no objects). When Storable is used, then anything
191that Storable can serialise and deserialise is allowed, and for the local 263that Storable can serialise and deserialise is allowed, and for the local
192node, anything can be passed. 264node, anything can be passed.
193 265
194=item kil $portid[, @reason] 266=item $local_port = port
195 267
196Kill the specified port with the given C<@reason>. 268Create a new local port object that can be used either as a pattern
269matching port ("full port") or a single-callback port ("miniport"),
270depending on how C<rcv> callbacks are bound to the object.
197 271
198If no C<@reason> is specified, then the port is killed "normally" (linked 272=item $port = port { my @msg = @_; $finished }
199ports will not be kileld, or even notified).
200 273
201Otherwise, linked ports get killed with the same reason (second form of 274Creates a "miniport", that is, a very lightweight port without any pattern
202C<mon>, see below). 275matching behind it, and returns its ID. Semantically the same as creating
276a port and calling C<rcv $port, $callback> on it.
203 277
204Runtime errors while evaluating C<rcv> callbacks or inside C<psub> blocks 278The block will be called for every message received on the port. When the
205will be reported as reason C<< die => $@ >>. 279callback returns a true value its job is considered "done" and the port
280will be destroyed. Otherwise it will stay alive.
206 281
207Transport/communication errors are reported as C<< transport_error => 282The message will be passed as-is, no extra argument (i.e. no port id) will
208$message >>. 283be passed to the callback.
209 284
285If you need the local port id in the callback, this works nicely:
286
287 my $port; $port = port {
288 snd $otherport, reply => $port;
289 };
290
291=cut
292
293sub rcv($@);
294
295sub port(;&) {
296 my $id = "$UNIQ." . $ID++;
297 my $port = "$NODE#$id";
298
299 if (@_) {
300 rcv $port, shift;
301 } else {
302 $PORT{$id} = sub { }; # nop
303 }
304
305 $port
306}
307
308=item reg $port, $name
309
310Registers the given port under the name C<$name>. If the name already
311exists it is replaced.
312
313A port can only be registered under one well known name.
314
315A port automatically becomes unregistered when it is killed.
316
317=cut
318
319sub reg(@) {
320 my ($port, $name) = @_;
321
322 $REG{$name} = $port;
323}
324
325=item rcv $port, $callback->(@msg)
326
327Replaces the callback on the specified miniport (after converting it to
328one if required).
329
330=item rcv $port, tagstring => $callback->(@msg), ...
331
332=item rcv $port, $smartmatch => $callback->(@msg), ...
333
334=item rcv $port, [$smartmatch...] => $callback->(@msg), ...
335
336Register callbacks to be called on matching messages on the given full
337port (after converting it to one if required).
338
339The callback has to return a true value when its work is done, after
340which is will be removed, or a false value in which case it will stay
341registered.
342
343The global C<$SELF> (exported by this module) contains C<$port> while
344executing the callback.
345
346Runtime errors wdurign callback execution will result in the port being
347C<kil>ed.
348
349If the match is an array reference, then it will be matched against the
350first elements of the message, otherwise only the first element is being
351matched.
352
353Any element in the match that is specified as C<_any_> (a function
354exported by this module) matches any single element of the message.
355
356While not required, it is highly recommended that the first matching
357element is a string identifying the message. The one-string-only match is
358also the most efficient match (by far).
359
360=cut
361
362sub rcv($@) {
363 my $port = shift;
364 my ($noderef, $portid) = split /#/, $port, 2;
365
366 ($NODE{$noderef} || add_node $noderef) == $NODE{""}
367 or Carp::croak "$port: rcv can only be called on local ports, caught";
368
369 if (@_ == 1) {
370 my $cb = shift;
371 delete $PORT_DATA{$portid};
372 $PORT{$portid} = sub {
373 local $SELF = $port;
374 eval {
375 &$cb
376 and kil $port;
377 };
378 _self_die if $@;
379 };
380 } else {
381 my $self = $PORT_DATA{$portid} ||= do {
382 my $self = bless {
383 id => $port,
384 }, "AnyEvent::MP::Port";
385
386 $PORT{$portid} = sub {
387 local $SELF = $port;
388
389 eval {
390 for (@{ $self->{rc0}{$_[0]} }) {
391 $_ && &{$_->[0]}
392 && undef $_;
393 }
394
395 for (@{ $self->{rcv}{$_[0]} }) {
396 $_ && [@_[1 .. @{$_->[1]}]] ~~ $_->[1]
397 && &{$_->[0]}
398 && undef $_;
399 }
400
401 for (@{ $self->{any} }) {
402 $_ && [@_[0 .. $#{$_->[1]}]] ~~ $_->[1]
403 && &{$_->[0]}
404 && undef $_;
405 }
406 };
407 _self_die if $@;
408 };
409
410 $self
411 };
412
413 "AnyEvent::MP::Port" eq ref $self
414 or Carp::croak "$port: rcv can only be called on message matching ports, caught";
415
416 while (@_) {
417 my ($match, $cb) = splice @_, 0, 2;
418
419 if (!ref $match) {
420 push @{ $self->{rc0}{$match} }, [$cb];
421 } elsif (("ARRAY" eq ref $match && !ref $match->[0])) {
422 my ($type, @match) = @$match;
423 @match
424 ? push @{ $self->{rcv}{$match->[0]} }, [$cb, \@match]
425 : push @{ $self->{rc0}{$match->[0]} }, [$cb];
426 } else {
427 push @{ $self->{any} }, [$cb, $match];
428 }
429 }
430 }
431
432 $port
433}
434
435=item $closure = psub { BLOCK }
436
437Remembers C<$SELF> and creates a closure out of the BLOCK. When the
438closure is executed, sets up the environment in the same way as in C<rcv>
439callbacks, i.e. runtime errors will cause the port to get C<kil>ed.
440
441This is useful when you register callbacks from C<rcv> callbacks:
442
443 rcv delayed_reply => sub {
444 my ($delay, @reply) = @_;
445 my $timer = AE::timer $delay, 0, psub {
446 snd @reply, $SELF;
447 };
448 };
449
450=cut
451
452sub psub(&) {
453 my $cb = shift;
454
455 my $port = $SELF
456 or Carp::croak "psub can only be called from within rcv or psub callbacks, not";
457
458 sub {
459 local $SELF = $port;
460
461 if (wantarray) {
462 my @res = eval { &$cb };
463 _self_die if $@;
464 @res
465 } else {
466 my $res = eval { &$cb };
467 _self_die if $@;
468 $res
469 }
470 }
471}
472
210=item $guard = mon $portid, $cb->(@reason) 473=item $guard = mon $port, $cb->(@reason)
211 474
212=item $guard = mon $portid, $otherport 475=item $guard = mon $port, $otherport
213 476
214=item $guard = mon $portid, $otherport, @msg 477=item $guard = mon $port, $otherport, @msg
215 478
216Monitor the given port and do something when the port is killed. 479Monitor the given port and do something when the port is killed.
217 480
218In the first form, the callback is simply called with any number 481In the first form, the callback is simply called with any number
219of C<@reason> elements (no @reason means that the port was deleted 482of C<@reason> elements (no @reason means that the port was deleted
297 mon $port2, $port1; 560 mon $port2, $port1;
298 561
299It means that if either one is killed abnormally, the other one gets 562It means that if either one is killed abnormally, the other one gets
300killed as well. 563killed as well.
301 564
302=item $local_port = port 565=item kil $port[, @reason]
303 566
304Create a new local port object that can be used either as a pattern 567Kill the specified port with the given C<@reason>.
305matching port ("full port") or a single-callback port ("miniport"),
306depending on how C<rcv> callbacks are bound to the object.
307 568
308=item $portid = port { my @msg = @_; $finished } 569If no C<@reason> is specified, then the port is killed "normally" (linked
570ports will not be kileld, or even notified).
309 571
310Creates a "mini port", that is, a very lightweight port without any 572Otherwise, linked ports get killed with the same reason (second form of
311pattern matching behind it, and returns its ID. 573C<mon>, see below).
312 574
313The block will be called for every message received on the port. When the 575Runtime errors while evaluating C<rcv> callbacks or inside C<psub> blocks
314callback returns a true value its job is considered "done" and the port 576will be reported as reason C<< die => $@ >>.
315will be destroyed. Otherwise it will stay alive.
316 577
317The message will be passed as-is, no extra argument (i.e. no port id) will 578Transport/communication errors are reported as C<< transport_error =>
318be passed to the callback. 579$message >>.
319
320If you need the local port id in the callback, this works nicely:
321
322 my $port; $port = port {
323 snd $otherport, reply => $port;
324 };
325
326=cut
327
328sub port(;&) {
329 my $id = "$UNIQ." . $ID++;
330 my $port = "$NODE#$id";
331
332 if (@_) {
333 my $cb = shift;
334 $PORT{$id} = sub {
335 local $SELF = $port;
336 eval {
337 &$cb
338 and kil $id;
339 };
340 _self_die if $@;
341 };
342 } else {
343 my $self = bless {
344 id => "$NODE#$id",
345 }, "AnyEvent::MP::Port";
346
347 $PORT_DATA{$id} = $self;
348 $PORT{$id} = sub {
349 local $SELF = $port;
350
351 eval {
352 for (@{ $self->{rc0}{$_[0]} }) {
353 $_ && &{$_->[0]}
354 && undef $_;
355 }
356
357 for (@{ $self->{rcv}{$_[0]} }) {
358 $_ && [@_[1 .. @{$_->[1]}]] ~~ $_->[1]
359 && &{$_->[0]}
360 && undef $_;
361 }
362
363 for (@{ $self->{any} }) {
364 $_ && [@_[0 .. $#{$_->[1]}]] ~~ $_->[1]
365 && &{$_->[0]}
366 && undef $_;
367 }
368 };
369 _self_die if $@;
370 };
371 }
372
373 $port
374}
375
376=item reg $portid, $name
377
378Registers the given port under the name C<$name>. If the name already
379exists it is replaced.
380
381A port can only be registered under one well known name.
382
383A port automatically becomes unregistered when it is killed.
384
385=cut
386
387sub reg(@) {
388 my ($portid, $name) = @_;
389
390 $REG{$name} = $portid;
391}
392
393=item rcv $portid, $callback->(@msg)
394
395Replaces the callback on the specified miniport (or newly created port
396object, see C<port>). Full ports are configured with the following calls:
397
398=item rcv $portid, tagstring => $callback->(@msg), ...
399
400=item rcv $portid, $smartmatch => $callback->(@msg), ...
401
402=item rcv $portid, [$smartmatch...] => $callback->(@msg), ...
403
404Register callbacks to be called on matching messages on the given port.
405
406The callback has to return a true value when its work is done, after
407which is will be removed, or a false value in which case it will stay
408registered.
409
410The global C<$SELF> (exported by this module) contains C<$portid> while
411executing the callback.
412
413Runtime errors wdurign callback execution will result in the port being
414C<kil>ed.
415
416If the match is an array reference, then it will be matched against the
417first elements of the message, otherwise only the first element is being
418matched.
419
420Any element in the match that is specified as C<_any_> (a function
421exported by this module) matches any single element of the message.
422
423While not required, it is highly recommended that the first matching
424element is a string identifying the message. The one-string-only match is
425also the most efficient match (by far).
426
427=cut
428
429sub rcv($@) {
430 my $portid = shift;
431 my ($noderef, $port) = split /#/, $port, 2;
432
433 ($NODE{$noderef} || add_node $noderef) == $NODE{""}
434 or Carp::croak "$noderef#$port: rcv can only be called on local ports, caught";
435
436 my $self = $PORT_DATA{$port}
437 or Carp::croak "$noderef#$port: rcv can only be called on message matching ports, caught";
438
439 "AnyEvent::MP::Port" eq ref $self
440 or Carp::croak "$noderef#$port: rcv can only be called on message matching ports, caught";
441
442 while (@_) {
443 my ($match, $cb) = splice @_, 0, 2;
444
445 if (!ref $match) {
446 push @{ $self->{rc0}{$match} }, [$cb];
447 } elsif (("ARRAY" eq ref $match && !ref $match->[0])) {
448 my ($type, @match) = @$match;
449 @match
450 ? push @{ $self->{rcv}{$match->[0]} }, [$cb, \@match]
451 : push @{ $self->{rc0}{$match->[0]} }, [$cb];
452 } else {
453 push @{ $self->{any} }, [$cb, $match];
454 }
455 }
456
457 $portid
458}
459
460=item $closure = psub { BLOCK }
461
462Remembers C<$SELF> and creates a closure out of the BLOCK. When the
463closure is executed, sets up the environment in the same way as in C<rcv>
464callbacks, i.e. runtime errors will cause the port to get C<kil>ed.
465
466This is useful when you register callbacks from C<rcv> callbacks:
467
468 rcv delayed_reply => sub {
469 my ($delay, @reply) = @_;
470 my $timer = AE::timer $delay, 0, psub {
471 snd @reply, $SELF;
472 };
473 };
474
475=cut
476
477sub psub(&) {
478 my $cb = shift;
479
480 my $port = $SELF
481 or Carp::croak "psub can only be called from within rcv or psub callbacks, not";
482
483 sub {
484 local $SELF = $port;
485
486 if (wantarray) {
487 my @res = eval { &$cb };
488 _self_die if $@;
489 @res
490 } else {
491 my $res = eval { &$cb };
492 _self_die if $@;
493 $res
494 }
495 }
496}
497
498=back
499
500=head1 FUNCTIONS FOR NODES
501
502=over 4
503
504=item become_public $noderef
505
506Tells the node to become a public node, i.e. reachable from other nodes.
507
508The first argument is the (unresolved) node reference of the local node
509(if missing then the empty string is used).
510
511It is quite common to not specify anything, in which case the local node
512tries to listen on the default port, or to only specify a port number, in
513which case AnyEvent::MP tries to guess the local addresses.
514
515=cut
516 580
517=back 581=back
518 582
519=head1 NODE MESSAGES 583=head1 NODE MESSAGES
520 584
562 626
563=back 627=back
564 628
565=head1 AnyEvent::MP vs. Distributed Erlang 629=head1 AnyEvent::MP vs. Distributed Erlang
566 630
567AnyEvent::MP got lots of its ideas from distributed erlang (erlang node 631AnyEvent::MP got lots of its ideas from distributed Erlang (Erlang node
568== aemp node, erlang process == aemp port), so many of the documents and 632== aemp node, Erlang process == aemp port), so many of the documents and
569programming techniques employed by erlang apply to AnyEvent::MP. Here is a 633programming techniques employed by Erlang apply to AnyEvent::MP. Here is a
570sample: 634sample:
571 635
572 http://www.erlang.se/doc/programming_rules.shtml 636 http://www.Erlang.se/doc/programming_rules.shtml
573 http://erlang.org/doc/getting_started/part_frame.html # chapters 3 and 4 637 http://Erlang.org/doc/getting_started/part_frame.html # chapters 3 and 4
574 http://erlang.org/download/erlang-book-part1.pdf # chapters 5 and 6 638 http://Erlang.org/download/Erlang-book-part1.pdf # chapters 5 and 6
575 http://erlang.org/download/armstrong_thesis_2003.pdf # chapters 4 and 5 639 http://Erlang.org/download/armstrong_thesis_2003.pdf # chapters 4 and 5
576 640
577Despite the similarities, there are also some important differences: 641Despite the similarities, there are also some important differences:
578 642
579=over 4 643=over 4
580 644
591 655
592Erlang uses processes that selctively receive messages, and therefore 656Erlang uses processes that selctively receive messages, and therefore
593needs a queue. AEMP is event based, queuing messages would serve no useful 657needs a queue. AEMP is event based, queuing messages would serve no useful
594purpose. 658purpose.
595 659
596(But see L<Coro::MP> for a more erlang-like process model on top of AEMP). 660(But see L<Coro::MP> for a more Erlang-like process model on top of AEMP).
597 661
598=item * Erlang sends are synchronous, AEMP sends are asynchronous. 662=item * Erlang sends are synchronous, AEMP sends are asynchronous.
599 663
600Sending messages in erlang is synchronous and blocks the process. AEMP 664Sending messages in Erlang is synchronous and blocks the process. AEMP
601sends are immediate, connection establishment is handled in the 665sends are immediate, connection establishment is handled in the
602background. 666background.
603 667
604=item * Erlang can silently lose messages, AEMP cannot. 668=item * Erlang can silently lose messages, AEMP cannot.
605 669
608and c, and the other side only receives messages a and c). 672and c, and the other side only receives messages a and c).
609 673
610AEMP guarantees correct ordering, and the guarantee that there are no 674AEMP guarantees correct ordering, and the guarantee that there are no
611holes in the message sequence. 675holes in the message sequence.
612 676
613=item * In erlang, processes can be declared dead and later be found to be 677=item * In Erlang, processes can be declared dead and later be found to be
614alive. 678alive.
615 679
616In erlang it can happen that a monitored process is declared dead and 680In Erlang it can happen that a monitored process is declared dead and
617linked processes get killed, but later it turns out that the process is 681linked processes get killed, but later it turns out that the process is
618still alive - and can receive messages. 682still alive - and can receive messages.
619 683
620In AEMP, when port monitoring detects a port as dead, then that port will 684In AEMP, when port monitoring detects a port as dead, then that port will
621eventually be killed - it cannot happen that a node detects a port as dead 685eventually be killed - it cannot happen that a node detects a port as dead
622and then later sends messages to it, finding it is still alive. 686and then later sends messages to it, finding it is still alive.
623 687
624=item * Erlang can send messages to the wrong port, AEMP does not. 688=item * Erlang can send messages to the wrong port, AEMP does not.
625 689
626In erlang it is quite possible that a node that restarts reuses a process 690In Erlang it is quite possible that a node that restarts reuses a process
627ID known to other nodes for a completely different process, causing 691ID known to other nodes for a completely different process, causing
628messages destined for that process to end up in an unrelated process. 692messages destined for that process to end up in an unrelated process.
629 693
630AEMP never reuses port IDs, so old messages or old port IDs floating 694AEMP never reuses port IDs, so old messages or old port IDs floating
631around in the network will not be sent to an unrelated port. 695around in the network will not be sent to an unrelated port.
637securely authenticate nodes. 701securely authenticate nodes.
638 702
639=item * The AEMP protocol is optimised for both text-based and binary 703=item * The AEMP protocol is optimised for both text-based and binary
640communications. 704communications.
641 705
642The AEMP protocol, unlike the erlang protocol, supports both 706The AEMP protocol, unlike the Erlang protocol, supports both
643language-independent text-only protocols (good for debugging) and binary, 707language-independent text-only protocols (good for debugging) and binary,
644language-specific serialisers (e.g. Storable). 708language-specific serialisers (e.g. Storable).
645 709
646It has also been carefully designed to be implementable in other languages 710It has also been carefully designed to be implementable in other languages
647with a minimum of work while gracefully degrading fucntionality to make the 711with a minimum of work while gracefully degrading fucntionality to make the
648protocol simple. 712protocol simple.
649 713
714=item * AEMP has more flexible monitoring options than Erlang.
715
716In Erlang, you can chose to receive I<all> exit signals as messages
717or I<none>, there is no in-between, so monitoring single processes is
718difficult to implement. Monitoring in AEMP is more flexible than in
719Erlang, as one can choose between automatic kill, exit message or callback
720on a per-process basis.
721
722=item * Erlang has different semantics for monitoring and linking, AEMP has the same.
723
724Monitoring in Erlang is not an indicator of process death/crashes,
725as linking is (except linking is unreliable in Erlang). In AEMP, the
726semantics of monitoring and linking are identical, linking is simply
727two-way monitoring with automatic kill.
728
650=back 729=back
651 730
652=head1 SEE ALSO 731=head1 SEE ALSO
653 732
654L<AnyEvent>. 733L<AnyEvent>.

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines