Imported Upstream version 3.3.3
[debian/amanda] / perl / Amanda / MainLoop.pod
1 /*
2  * Copyright (c) 2009-2012 Zmanda, Inc.  All Rights Reserved.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17  *
18  * Contact information: Zmanda Inc., 465 S. Mathilda Ave., Suite 300
19  * Sunnyvale, CA 94085, USA, or: http://www.zmanda.com
20  */
21
22 %perlcode %{
23
24 =head1 NAME
25
26 Amanda::MainLoop - Perl interface to the Glib MainLoop
27
28 =head1 SYNOPSIS
29
30     use Amanda::MainLoop;
31
32     my $to = Amanda::MainLoop::timeout_source(2000);
33     $to->set_callback(sub {
34         print "Time's Up!\n";
35         $to->remove();              # dont' re-queue this timeout
36         Amanda::MainLoop::quit();   # return from Amanda::MainLoop::run
37     });
38
39     Amanda::MainLoop::run();
40
41 Note that all functions in this module are individually available for
42 export, e.g.,
43
44     use Amanda::MainLoop qw(run quit);
45
46 =head1 OVERVIEW
47
48 The main event loop of an application is a tight loop which waits for
49 events, and calls functions to respond to those events.  This design
50 allows an IO-bound application to multitask within a single thread, by
51 responding to IO events as they occur instead of blocking on
52 particular IO operations.
53
54 The Amanda security API, transfer API, and other components rely on
55 the event loop to allow them to respond to their own events in a
56 timely fashion.
57
58 The overall structure of an application, then, is to initialize its
59 state, register callbacks for some events, and begin looping.  In each
60 iteration, the loop waits for interesting events to occur (data
61 available for reading or writing, timeouts, etc.), and then calls
62 functions to handle those interesting things.  Thus, the application
63 spends most of its time waiting.  When some application-defined state
64 is reached, the loop is terminated and the application cleans up and
65 exits.
66
67 The Glib main loop takes place within a call to
68 C<Amanda::MainLoop::run()>.  This function executes until a call to
69 C<Amanda::MainLoop::quit()> occurs, at which point C<run()> returns.
70 You can check whether the loop is running with
71 C<Amanda::MainLoop::is_running()>.
72
73 =head1 HIGH-LEVEL INTERFACE
74
75 The functions in this section are intended to make asynchronous
76 programming as simple as possible.  They are implemented on top of the
77 interfaces described in the LOW-LEVEL INTERFACE section.
78
79 =head3 call_later
80
81 In most cases, a callback does not need to be invoked immediately.  In
82 fact, because Perl does not do tail-call optimization, a long chain of
83 callbacks may cause the perl stack to grow unnecessarily.
84
85 The solution is to queue the callback for execution on the next
86 iteration of the main loop, and C<call_later($cb, @args)> does exactly
87 this.
88
89     sub might_delay {
90         my ($cb) = @_;
91         if (can_do_it_now()) {
92             my $result = do_it();
93             Amanda::MainLoop::call_later($cb, $result)
94         } else {
95             # ..
96         }
97     }
98
99 When starting the main loop, an application usually has a sub that
100 should run after the loop has started.  C<call_later> works in this
101 situation, too.
102
103     my $main = sub {
104         # ..
105         Amanda::MainLoop::quit();
106     };
107     Amanda::MainLoop::call_later($main);
108     # ..
109     Amanda::MainLoop::run();
110
111 =head3 make_cb
112
113 As an optimization, C<make_cb> wraps a sub with a call to call_later
114 while also naming the sub (using C<Sub::Name>, if available):
115
116     my $fetched_cb = make_cb(fetched_cb => sub {
117         # .. callback body
118     }
119
120 In general, C<make_cb> should be used whenever a callback is passed to
121 some other library.  For example, the Changer API (see
122 L<Amanda::Changer>) might be invoked like this:
123
124     my $reset_finished_cb = make_cb(reset_finished_cb => sub {
125         my ($err) = @_;
126         die "while resetting: $err" if $err;
127         # ..
128     });
129
130 Be careful I<not> to use C<make_cb> in cases where some action must
131 take place before the next iteration of the main loop.  In practice,
132 this means C<make_cb> should be avoided with file-descriptor
133 callbacks, which will trigger repeatedly until the descriptors' needs
134 are addressed.
135
136 C<make_cb> is exported automatically.
137
138 =head3 call_after
139
140 Sometimes you need the MainLoop equivalent of C<sleep()>.  That comes
141 in the form of C<call_later($delay, $cb, @args)>, which takes a delay
142 (in milliseconds), a sub, and an arbitrary number of arguments.  The
143 sub is called with the arguments after the delay has elapsed.
144
145     sub countdown {
146         my $counter;
147         $counter = sub {
148             print "$i..\n";
149             if ($i) {
150                 Amanda::MainLoop::call_after(1000, $counter, $i-1);
151             }
152         }
153         $counter->(10);
154     }
155
156 The function returns the underlying event source (see below), enabling
157 the caller to cancel the pending call:
158
159     my $tosrc = Amanda::MainLoop::call_after(15000, $timeout_cb):
160     # ...data arrives before timeout...
161     $tosrc->remove();
162
163 =head3 call_on_child_termination
164
165 To monitor a child process for termination, give its pid to
166 C<call_on_child_termination($pid, $cb, @args)>.  When the child exits
167 for any reason, this will collect its exit status (via C<waitpid>) and
168 call C<$cb> as
169
170     $cb->($exitstatus, @args);
171
172 Like C<call_after>, this function returns the event source to allow
173 early cancellation if desired.
174
175 =head3 async_read
176
177     async_read(
178         fd => $fd,
179         size => $size,        # optional, default 0
180         async_read_cb => $async_read_cb,
181         args => [ .. ]);      # optional
182
183 This function will read C<$size> bytes when they are available from
184 file descriptor C<$fd>, and invoke the callback with the results:
185
186     $async_read_cb->($err, $buf, @args);
187
188 If C<$size> is zero, then the callback will get whatever data is
189 available as soon as it is available, up to an arbitrary buffer size.
190 If C<$size> is nonzero, then a short read may still occur if C<$size>
191 bytes do not become available simultaneously.  On EOF, C<$buf> will be
192 the empty string.  It is the caller's responsibility to set C<$fd> to
193 non-blocking mode.  Note that not all operating sytems generate errors
194 that might be reported here.  For example, on Solaris an invalid file
195 descriptor will be silently ignored.
196
197 The return value is an event source, and calling its C<remove> method
198 will cancel the read.  It is an error to have more than one
199 C<async_read> operation on a single file descriptor at any time, and
200 will lead to unpredictable results.
201
202 This function adds a new FdSource every time it is invoked, so it is
203 not well-suited to processing large amounts of data.  For that
204 purpose, consider using the low-level interface or, better, the
205 transfer architecture (see L<Amanda::Xfer>).
206
207 =head3 async_write
208
209     async_write(
210         fd => $fd,
211         data => $data,
212         async_write_cb => $async_write_cb,
213         args => [ .. ]);      # optional
214
215 This function will write C<$data> to file descriptor C<$fd> and invoke
216 the callback with the number of bytes written:
217
218     $cb->($err, $bytes_written, @args);
219
220 If C<$bytes_written> is less than then length of <$data>, then an
221 error occurred, and is given in C<$err>.  As for C<async_read>, the
222 caller should set C<$fd> to non-blocking mode.  Multiple parallel
223 invocations of this function for the same file descriptor are allowed
224 and will be serialized in the order the calls were made:
225
226     async_write($fd, "HELLO!\n",
227         async_write_cb => make_cb(wrote_hello => sub {
228             print "wrote 'HELLO!'\n";
229         }));
230     async_write($fd, "GOODBYE!\n",
231         async_write_cb => make_cb(wrote_goodbye => sub {
232             print "wrote 'GOODBYE!'\n";
233         }));
234
235 In this case, the two strings are guaranteed to be written in the same
236 order, and the callbacks will be called in the correct order.
237
238 Like async_read, this function may add a new FdSource every time it is
239 invoked, so it is not well-suited to processing large amounts of data.
240
241 =head3 synchronized
242
243 Java has the notion of a "synchronized" method, which can only execute in one
244 thread at any time.  This is a particular application of a lock, in which the
245 lock is acquired when the method begins, and released when it finishes.
246
247 With C<Amanda::MainLoop>, this functionality is generally not needed because
248 there is no unexpected preemeption. However, if you break up a long-running
249 operation (that doesn't allow concurrency) into several callbacks, you'll need
250 to ensure that at most one of those operations is going on at a time. The
251 C<synchronized> function manages that for you.
252
253 The function takes a C<$lock> argument, which should be initialized to an empty
254 arrayref (C<[]>).  It is used like this:
255
256     use Amanda::MainLoop 'synchronized';
257     # ..
258     sub dump_data {
259         my $self = shift;
260         my ($arg1, $arg2, $dump_cb) = @_;
261
262         synchronized($self->{'lock'}, $dump_cb, sub {
263             my ($dump_cb) = @_; # IMPORTANT! See below
264             $self->do_dump_data($arg1, $arg2, $dump_cb);
265         };
266     }
267
268 Here, C<do_dump_data> may take a long time to complete (perhaps it starts
269 a long-running data transfer) but only one such operation is allowed at any
270 time and other C<Amanda::MainLoop> callbacks may occur (e.g. a timeout).
271 When the critical operation is complete, it calls C<$dump_cb> which will
272 release the lock before transferring control to the caller.
273
274 Note that the C<$dump_cb> in the inner C<sub> shadows that in
275 C<dump_data> -- this is intentional, the a call to the the inner
276 C<$dump_cb> is how C<synchronized> knows that the operation has completed.
277
278 Several methods may be synchronized with one another by simply sharing the same
279 lock.
280
281 =head1 ASYNCHRONOUS STYLE
282
283 When writing asynchronous code, it's easy to write code that is *very*
284 difficult to read or debug.  The suggestions in this section will help
285 write code that is more readable, and also ensure that all asynchronous
286 code in Amanda uses similar, common idioms.
287
288 =head2 USING CALLBACKS
289
290 Most often, callbacks are short, and can be specified as anonymous
291 subs.  They should be specified with make_cb, like this:
292
293     some_async_function(make_cb(foo_cb => sub {
294         my ($x, $y) = @_;
295         # ...
296     }));
297
298 If a callback is more than about two lines, specify it in a named
299 variable, rather than directly in the function call:
300
301     my $foo_cb = make_cb(foo_cb => sub {
302         my ($src) = @_;
303         # .
304         # .  long function
305         # .
306     });
307     some_async_function($foo_cb);
308
309 When using callbacks from an object-oriented package, it is often
310 useful to treat a method as a callback.  This requires an anonymous
311 sub "wrapper", which can be written on one line:
312
313     some_async_function(sub { $self->foo_cb(@_) });
314
315 =head2 LINEARITY
316
317 The single most important factor in readability is linearity.  If a function
318 that performs operations A, B, and C in that order, then the code for A, B, and
319 C should appear in that order in the source file.  This seems obvious, but it's
320 all too easy to write
321
322     sub three_ops {
323         my $do_c = sub { .. };
324         my $do_b = sub { .. $do_c->() .. };
325         my $do_a = sub { .. $do_b->() .. };
326         $do_a->();
327     }
328
329 Which isn't very readable.  Be readable.
330
331 =head2 SINGLE ENTRY AND EXIT
332
333 Amanda's use of callbacks emulates continuation-passing style.  As such, when a
334 function finishes -- whether successfully or with an error -- it should call a
335 single callback.  This ensures that the function has a simple control
336 interface: perform the operation and call the callback.
337
338 =head2 MULTIPLE STEPS
339
340 Some operations require a long squence of asynchronous operations.  For
341 example, often the results of one operation are required to initiate
342 another.  The I<step> syntax is useful to make this much more readable, and
343 also eliminate some nasty reference-counting bugs.  The idea is that each "step"
344 in the process gets its own sub, and then each step calls the next step.  The
345 first step defined will be called automatically.
346
347     sub send_file {
348         my ($hostname, $port, $data, $sendfile_cb) = @_;
349         my ($addr, $socket); # shared lexical variables
350         my $steps = define_steps
351                 cb_ref => \$sendfile_cb;
352         step lookup_addr => sub {
353             return async_gethostbyname(hostname => $hostname,
354                                 ghbn_cb => $steps->{'got_addr'});
355         };
356         step ghbn_cb => sub {
357             my ($err, $hostinfo) = @_;
358             die $err if $err;
359             $addr = $hostinfo->{'ipaddr'};
360             return $steps->{'connect'}->();
361         };
362         step connect => sub {
363             return async_connect(
364                 ipaddr => $addr,
365                 port => $port,
366                 connect_cb => $steps->{'connect_cb'},
367             );
368         };
369         step connect_cb => sub {
370             my ($err, $conn_sock) = @_;
371             die $err if $err;
372             $socket = $conn_sock;
373             return $steps->{'write_block'}->();
374         };
375         # ...
376     }
377
378 The C<define_steps> function sets the stage.  It is given a reference to the
379 callback for this function (recall there is only one exit point!), and
380 "patches" that reference to free C<$steps>, which otherwise forms a reference
381 loop, on exit.
382
383 WARNING: if the function or method needs to do any kind of setup before its
384 first step, that setup should be done either in a C<setup> step or I<before>
385 the C<define_steps> invocation.  Do not write any statements other than step
386 declarations after the C<define_steps> call.
387
388 Note that there are more steps in this example than are strictly necessary: the
389 body of C<connect> could be appended to C<ghbn_cb>.  The extra steps make the
390 overall operation more readable by adding "punctuation" to separate the task of
391 handling a callback (C<ghbn_cb>) from starting the next operation (C<connect>).
392
393 Also note that the enclosing scope contains some lexical (C<my>)
394 variables which are shared by several of the callbacks.
395
396 All of the steps are wrapped by C<make_cb>, so each step will be executed on a
397 separate iteration of the MainLoop.  This generally has the effect of making
398 asynchronous functions share CPU time more fairly.  Sometimes, especially when
399 using the low-level interface, a callback must be called immediately.  To
400 achieve this for all callbacks, add C<< immediate => 1 >> to the C<define_steps>
401 invocation:
402
403     my $steps = define_steps
404             cb_ref => \$finished_cb,
405             immediate => 1;
406
407 To do the same for a single step, add the same keyword to the C<step> invocation:
408
409     step immediate => 1,
410          connect => sub { .. };
411
412 In some case, you want to execute some code when the step finish, it can
413 be done by defining a finalize code in define_steps:
414
415     my $steps = define_steps
416             cb_ref => \$finished_cb,
417             finalize => sub { .. };
418
419 =head2 JOINING ASYNCHRONOUS "THREADS"
420
421 With slow operations, it is often useful to perform multiple operations
422 simultaneously.  As an example, the following code might run two system
423 commands simultaneously and capture their output:
424
425     sub run_two_commands {
426         my ($finished_cb) = @_;
427         my $running_commands = 0;
428         my ($result1, $result2);
429         my $steps = define_steps
430             cb_ref => \$finished_cb;
431         step start => sub {
432             $running_commands++;
433             run_command($command1,
434                 run_cb => $steps->{'command1_done'});
435             $running_commands++;
436             run_command($command2,
437                 run_cb => $steps->{'command2_done'});
438         };
439         step command1_done => sub {
440             $result1 = $_[0];
441             $steps->{'maybe_done'}->();
442         };
443         step command2_done => sub {
444             $result2 = $_[0];
445             $steps->{'maybe_done'}->();
446         };
447         step maybe_done => sub {
448             return if --$running_commands; # not done yet
449             $finished_cb->($result1, $result2);
450         };
451     }
452
453 It is tempting to optimize out the C<$running_commands> with something like:
454
455     step maybe_done { ## BAD!
456         return unless defined $result1 and defined $result2;
457         $finished_cb->($result1, $result2);
458     }
459
460 However this can lead to trouble.  Remember that define_steps automatically
461 applies C<make_cb> to each step, so a C<maybe_done> is not invoked immediately
462 by C<command1_done> and C<command2_done> - instead, C<maybe_done> is scheduled
463 for invocation in the next loop of the mainloop (via C<call_later>).  If both
464 commands finish before C<maybe_done> is invoked, C<call_later> will be called
465 I<twice>, with both C<$result1> and C<$result2> defined both times.  The result
466 is that C<$finished_cb> is called twice, and mayhem ensues.
467
468 This is a complex case, but worth understanding if you want to be able to debug
469 difficult MainLoop bugs.
470
471 =head2 WRITING ASYNCHRONOUS INTERFACES
472
473 When designing a library or interface that will accept and invoke
474 callbacks, follow these guidelines so that users of the interface will
475 not need to remember special rules.
476
477 Each callback signature within a package should always have the same
478 name, ending with C<_cb>.  For example, a hypothetical
479 C<Amanda::Estimate> module might provide its estimates through a
480 callback with four parameters.  This callback should be referred to as
481 C<estimate_cb> throughout the package, and its parameters should be
482 clearly defined in the package's documentation.  It should take
483 positional parameters only.  If error conditions must also be
484 communicated via the callback, then the first parameter should be an
485 C<$error> parameter, which is undefined when no error has occurred.
486 The Changer API's C<res_cb> is typical of such a callback signature.
487
488 A caller can only know that an operation is complete by the invocation
489 of the callback, so it is important that a callback be invoked
490 I<exactly once> in all circumstances.  Even in an error condition, the
491 caller needs to know that the operation has failed.  Also beware of
492 bugs that might cause a callback to be invoked twice.
493
494 Functions or methods taking callbacks as arguments should either take
495 only a callback (like C<call_later>), or take hash-key parameters,
496 where the callback's key is the signature name.  For example, the
497 C<Amanda::Estimate> package might define a function like
498 C<perform_estimate>, invoked something like this:
499
500     my $estimate_cb = make_cb(estimate_cb => sub {
501         my ($err, $size, $level) = @_;
502         die $err if $err;
503         # ...
504     });
505     Amanda::Estimate::perform_estimate(
506         host => $host,
507         disk => $disk,
508         estimate_cb => $estimate_cb,
509     );
510
511 When invoking a user-supplied callback within the library, there is no
512 need to wrap it in a C<call_later> invocation, as the user already
513 supplied that wrapper via C<make_cb>, or is not interested in using
514 such a wrapper.
515
516 Callbacks are a form of continuation
517 (L<http://en.wikipedia.org/wiki/Continuations>), and as such should
518 only be called at the I<end> of a function.  Do not do anything after
519 invoking a callback, as you cannot know what processing has gone on in
520 the callback.
521
522     sub estimate_done {
523         # ...
524         $self->{'estimate_cb'}->(undef, $size, $level);
525         $self->{'estimate_in_progress'} = 0; # BUG!!
526     }
527
528 In this case, the C<estimate_cb> invocation may have called
529 C<perform_estimate> again, setting C<estimate_in_progress> back to 1.
530 A technique to avoid this pitfall is to always C<return> a callback's
531 result, even though that result is not important.  This makes the bug
532 much more apparent:
533
534     sub estimate_done {
535         # ...
536         return $self->{'estimate_cb'}->(undef, $size, $level);
537         $self->{'estimate_in_progress'} = 0; # BUG (this just looks silly)
538     }
539
540 =head1 LOW-LEVEL INTERFACE
541
542 MainLoop events are generated by event sources.  A source may produce
543 multiple events over its lifetime.  The higher-level methods in the
544 previous section provide a more Perlish abstraction of event sources,
545 but for efficiency it is sometimes necessary to use event sources
546 directly.
547
548 The method C<< $src->set_callback(\&cb) >> sets the function that will
549 be called for a given source, and "attaches" the source to the main
550 loop so that it will begin generating events.  The arguments to the
551 callback depend on the event source, but the first argument is always
552 the source itself.  Unless specified, no other arguments are provided.
553
554 Event sources persist until they are removed with
555 C<< $src->remove() >>, even if the source itself is no longer accessible from Perl.
556 Although Glib supports it, there is no provision for "automatically"
557 removing an event source.  Also, calling C<< $src->remove() >> more than
558 once is a potentially-fatal error. As an example:
559
560   sub start_timer {
561     my ($loops) = @_;
562     Amanda::MainLoop::timeout_source(200)->set_callback(sub {
563       my ($src) = @_;
564       print "timer\n";
565       if (--$loops <= 0) {
566         $src->remove();
567         Amanda::MainLoop::quit();
568       }
569     });
570   }
571   start_timer(10);
572   Amanda::MainLoop::run();
573
574 There is no means in place to specify extra arguments to be provided
575 to a source callback when it is set.  If the callback needs access to
576 other data, it should use a Perl closure in the form of lexically
577 scoped variables and an anonymous sub.  In fact, this is exactly what
578 the higher-level functions (described above) do.
579
580 =head2 Timeout
581
582   my $src = Amanda::MainLoop::timeout_source(10000);
583
584 A timeout source will create events at the specified interval,
585 specified in milliseconds (thousandths of a second).  The events will
586 continue until the source is destroyed.
587
588 =head2 Idle
589
590   my $src = Amanda::MainLoop::idle_source(2);
591
592 An idle source will create events continuously except when a
593 higher-priority source is emitting events.  Priorities are generally
594 small positive integers, with larger integers denoting lower
595 priorities.  The events will continue until the source is destroyed.
596
597 =head2 Child Watch
598
599   my $src = Amanda::MainLoop::child_watch_source($pid);
600
601 A child watch source will issue an event when the process with the
602 given PID dies.  To avoid race conditions, it will issue an event even
603 if the process dies before the source is created.  The callback is
604 called with three arguments: the event source, the PID, and the
605 child's exit status.
606
607 Note that this source is totally incompatible with any thing that
608 would cause perl to change the SIGCHLD handler.  If SIGCHLD is
609 changed, under some circumstances the module will recognize this
610 circumstance, add a warning to the debug log, and continue operating.
611 However, it is impossible to catch all possible situations.
612
613 =head2 File Descriptor
614
615   my $src = Amanda::MainLoop::fd_source($fd, $G_IO_IN);
616
617 This source will issue an event whenever one of the given conditions
618 is true for the given file (a file handle or integer file descriptor).
619 The conditions are from Glib's GIOCondition, and are C<$G_IO_IN>,
620 C<G_IO_OUT>, C<$G_IO_PRI>, C<$G_IO_ERR>, C<$G_IO_HUP>, and
621 C<$G_IO_NVAL>.  These constants are available with the import tag
622 C<:GIOCondition>.
623
624 Generally, when reading from a file descriptor, use
625 C<$G_IO_IN|$G_IO_HUP|$G_IO_ERR> to ensure that an EOF triggers an
626 event as well.  Writing to a file descriptor can simply use
627 C<$G_IO_OUT|$G_IO_ERR>.
628
629 The callback attached to an FdSource should read from or write to the
630 underlying file descriptor before returning, or it will be called
631 again in the next iteration of the main loop, which can lead to
632 unexpected results.  Do I<not> use C<make_cb> here!
633
634 =head2 Combining Event Sources
635
636 Event sources are often set up in groups, e.g., a long-term operation
637 and a timeout.  When this is the case, be careful that all sources are
638 removed when the operation is complete.  The easiest way to accomplish
639 this is to include all sources in a lexical scope and remove them at
640 the appropriate times:
641
642     {
643         my $op_src = long_operation_src();
644         my $timeout_src = Amanda::MainLoop::timeout_source($timeout);
645
646         sub finish {
647             $op_src->remove();
648             $timeout_src->remove();
649         }
650
651         $op_src->set_callback(sub {
652             print "Operation complete\n";
653             finish();
654         });
655
656         $timeout_src->set_callback(sub {
657             print "Operation timed out\n";
658             finish();
659         });
660     }
661
662 =head2 Relationship to Glib
663
664 Glib's main event loop is described in the Glib manual:
665 L<http://library.gnome.org/devel/glib/stable/glib-The-Main-Event-Loop.html>.
666 Note that Amanda depends only on the functionality available in
667 Glib-2.2.0, so many functions described in that document are not
668 available in Amanda.  This module provides a much-simplified interface
669 to the glib library, and is not intended as a generic wrapper for it:
670 Amanda's perl-accessible main loop only runs a single C<GMainContext>,
671 and always runs in the main thread; and (aside from idle sources),
672 event priorities are not accessible from Perl.
673
674 =cut
675
676
677 %}