annotate pkg/controllers/manualimports.go @ 1708:49e047c2106e

Imports: Made imports re-runnable if they fail.
author Sascha L. Teichmann <sascha.teichmann@intevation.de>
date Tue, 08 Jan 2019 13:35:44 +0100
parents 53304db85888
children 807569b08513
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
1 // This is Free Software under GNU Affero General Public License v >= 3.0
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
2 // without warranty, see README.md and license for details.
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
3 //
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
4 // SPDX-License-Identifier: AGPL-3.0-or-later
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
5 // License-Filename: LICENSES/AGPL-3.0.txt
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
6 //
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
7 // Copyright (C) 2018 by via donau
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
8 // – Österreichische Wasserstraßen-Gesellschaft mbH
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
9 // Software engineering by Intevation GmbH
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
10 //
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
11 // Author(s):
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
12 // * Sascha L. Teichmann <sascha.teichmann@intevation.de>
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
13 // * Raimund Renkert <raimund.renkert@intevation.de>
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
14
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
15 package controllers
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
16
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
17 import (
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
18 "database/sql"
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
19 "log"
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
20 "net/http"
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
21 "time"
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
22
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
23 "gemma.intevation.de/gemma/pkg/auth"
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
24 "gemma.intevation.de/gemma/pkg/common"
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
25 "gemma.intevation.de/gemma/pkg/imports"
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
26 "gemma.intevation.de/gemma/pkg/models"
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
27 )
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
28
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
29 func retry(a common.Attributes) (time.Time, int) {
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
30 due, _ := a.Time("due")
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
31 retries, ok := a.Int("retries")
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
32 if !ok {
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
33 retries = -1
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
34 }
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
35 return due, retries
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
36 }
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
37
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
38 func importBottleneck(input interface{}) (interface{}, time.Time, int, bool, bool) {
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
39 bi := input.(*models.BottleneckImport)
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
40 bn := &imports.Bottleneck{
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
41 URL: bi.URL,
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
42 Insecure: bi.Insecure,
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
43 }
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
44 due, retries := retry(bi.Attributes)
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
45 return bn, due, retries, bi.SendEmail, false
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
46 }
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
47
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
48 func importGaugeMeasurement(input interface{}) (interface{}, time.Time, int, bool, bool) {
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
49 gi := input.(*models.GaugeMeasurementImport)
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
50 gm := &imports.GaugeMeasurement{
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
51 URL: gi.URL,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
52 Insecure: gi.Insecure,
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
53 }
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
54 due, retries := retry(gi.Attributes)
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
55 return gm, due, retries, gi.SendEmail, true
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
56 }
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
57
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
58 func importFairwayAvailability(input interface{}) (interface{}, time.Time, int, bool, bool) {
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
59 fai := input.(*models.FairwayAvailabilityImport)
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
60 fa := &imports.FairwayAvailability{
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
61 URL: fai.URL,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
62 Insecure: fai.Insecure,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
63 }
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
64 due, retries := retry(fai.Attributes)
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
65 return fa, due, retries, fai.SendEmail, true
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
66 }
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
67
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
68 func importWaterwayAxis(input interface{}) (interface{}, time.Time, int, bool, bool) {
1677
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
69 wxi := input.(*models.WaterwayAxisImport)
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
70 wx := &imports.WaterwayAxis{
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
71 URL: wxi.URL,
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
72 FeatureType: wxi.FeatureType,
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
73 SortBy: wxi.SortBy,
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
74 }
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
75 due, retries := retry(wxi.Attributes)
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
76 return wx, due, retries, wxi.SendEmail, true
1677
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
77 }
53304db85888 Waterway axis import: Added route for manual import.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1667
diff changeset
78
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
79 func manualImport(
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
80 kind imports.JobKind,
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
81 setup func(interface{}) (interface{}, time.Time, int, bool, bool),
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
82 ) func(interface{}, *http.Request, *sql.Conn) (JSONResult, error) {
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
83
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
84 return func(input interface{}, req *http.Request, _ *sql.Conn) (
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
85 jr JSONResult, err error) {
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
86
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
87 what, due, retries, sendEmail, autoAccept := setup(input)
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
88
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
89 var serialized string
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
90 if serialized, err = common.ToJSONString(what); err != nil {
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
91 return
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
92 }
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
93
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
94 session, _ := auth.GetSession(req)
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
95
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
96 var jobID int64
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
97 if jobID, err = imports.AddJob(
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
98 kind,
1708
49e047c2106e Imports: Made imports re-runnable if they fail.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1677
diff changeset
99 due, retries,
1667
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
100 session.User,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
101 sendEmail, autoAccept,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
102 serialized,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
103 ); err != nil {
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
104 return
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
105 }
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
106
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
107 log.Printf("info: added import #%d to queue\n", jobID)
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
108
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
109 result := struct {
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
110 ID int64 `json:"id"`
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
111 }{
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
112 ID: jobID,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
113 }
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
114
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
115 jr = JSONResult{
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
116 Code: http.StatusCreated,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
117 Result: &result,
aaa05d3c4aac Deduplicated code for triggering manual imports.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents: 1646
diff changeset
118 }
1534
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
119 return
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
120 }
165f31b71042 Bottleneck import: Added /api/imports/bottleneck POST endpoint.
Sascha L. Teichmann <sascha.teichmann@intevation.de>
parents:
diff changeset
121 }