# HG changeset patch # User Sascha L. Teichmann # Date 1551110553 -3600 # Node ID 86c7a023400e22b5331a4c5faf941accb00b7d51 # Parent 123e7f43b676edc43db5f707d0d7284d7b1dc70e Started experimental octree diff branch. diff -r 123e7f43b676 -r 86c7a023400e cmd/octreediff/db.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/octreediff/db.go Mon Feb 25 17:02:33 2019 +0100 @@ -0,0 +1,52 @@ +// This is Free Software under GNU Affero General Public License v >= 3.0 +// without warranty, see README.md and license for details. +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// License-Filename: LICENSES/AGPL-3.0.txt +// +// Copyright (C) 2018 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Sascha L. Teichmann + +package main + +import ( + "database/sql" + "flag" + + "github.com/jackc/pgx" + "github.com/jackc/pgx/stdlib" +) + +var ( + dbhost = flag.String("dbhost", "localhost", "database host") + dbport = flag.Uint("dbport", 5432, "database port") + dbname = flag.String("dbname", "gemma", "database user") + dbuser = flag.String("dbuser", "scott", "database user") + dbpassword = flag.String("dbpw", "tiger", "database password") + dbssl = flag.String("dbssl", "prefer", "database SSL mode") +) + +func run(fn func(*sql.DB) error) error { + + // To ease SSL config ride a bit on parsing. + cc, err := pgx.ParseConnectionString("sslmode=" + *dbssl) + if err != nil { + return err + } + + // Do the rest manually to allow whitespace in user/password. + cc.Host = *dbhost + cc.Port = uint16(*dbport) + cc.User = *dbuser + cc.Password = *dbpassword + cc.Database = *dbname + + db := stdlib.OpenDB(cc) + defer db.Close() + + return fn(db) +} diff -r 123e7f43b676 -r 86c7a023400e cmd/octreediff/main.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cmd/octreediff/main.go Mon Feb 25 17:02:33 2019 +0100 @@ -0,0 +1,149 @@ +// This is Free Software under GNU Affero General Public License v >= 3.0 +// without warranty, see README.md and license for details. +// +// SPDX-License-Identifier: AGPL-3.0-or-later +// License-Filename: LICENSES/AGPL-3.0.txt +// +// Copyright (C) 2018 by via donau +// – Österreichische Wasserstraßen-Gesellschaft mbH +// Software engineering by Intevation GmbH +// +// Author(s): +// * Sascha L. Teichmann + +package main + +import ( + "context" + "database/sql" + "flag" + "fmt" + "log" + "runtime" + "sync" + "time" + + "gemma.intevation.de/gemma/pkg/common" + "gemma.intevation.de/gemma/pkg/octree" +) + +var ( + bottleneck = flag.String("bottleneck", "", "name of the bottleneck") + first = flag.String("first", "", "date of the first sounding result") + second = flag.String("second", "", "date of the second sounding result") +) + +const ( + loadOctreeSQL = ` +SELECT sr.octree_index +FROM waterway.sounding_results sr JOIN waterway.bottlenecks bn + ON sr.bottleneck_id = bn.id +WHERE bn.bottleneck_id = $1 AND sr.date_info = $2::date + AND sr.octree_index IS NOT NULL` +) + +func check(err error) { + if err != nil { + log.Fatalf("error: %v\n", err) + } +} + +func process(bottleneck string, firstDate, secondDate time.Time) error { + start := time.Now() + defer func() { log.Printf("processing took %v\n", time.Since(start)) }() + + ctx := context.Background() + + return run(func(db *sql.DB) error { + + conn, err := db.Conn(ctx) + if err != nil { + return err + } + defer conn.Close() + + type load struct { + date time.Time + data []byte + err *error + dst **octree.Tree + } + + out := make(chan *load) + wg := new(sync.WaitGroup) + + n := runtime.NumCPU() + if n > 2 { + n = 2 + } + + for i := 0; i < n; i++ { + wg.Add(1) + go func() { + defer wg.Done() + for l := range out { + if *l.err == nil { + *l.dst, *l.err = octree.Deserialize(l.data) + } + } + }() + } + + var firstErr, secondErr error + var first, second *octree.Tree + + for _, l := range []*load{ + {date: firstDate, dst: &first, err: &firstErr}, + {date: secondDate, dst: &second, err: &secondErr}, + } { + var data []byte + if err := conn.QueryRowContext( + ctx, + loadOctreeSQL, + bottleneck, + l.date, + ).Scan(&data); err != nil { + *l.err = err + } else { + l.data = data + } + out <- l + } + close(out) + + wg.Wait() + + if firstErr != nil || secondErr != nil { + if firstErr != nil && secondErr != nil { + return fmt.Errorf("%v, %v", firstErr, secondErr) + } + if firstErr != nil { + return firstErr + } + return secondErr + } + + log.Printf("loading took %v\n", time.Since(start)) + + // TODO: Do the diff. + _, _ = first, second + + return nil + }) +} + +func main() { + + flag.Parse() + + firstDate, err := time.Parse(common.DateFormat, *first) + check(err) + secondDate, err := time.Parse(common.DateFormat, *second) + check(err) + + if *bottleneck == "" { + log.Fatalln("Missing bottleneck name") + } + + check(process(*bottleneck, firstDate, secondDate)) +} diff -r 123e7f43b676 -r 86c7a023400e pkg/octree/cache.go --- a/pkg/octree/cache.go Mon Feb 25 16:16:33 2019 +0100 +++ b/pkg/octree/cache.go Mon Feb 25 17:02:33 2019 +0100 @@ -139,7 +139,7 @@ } } - tree, err := deserialize(data) + tree, err := Deserialize(data) if err != nil { return nil, err } diff -r 123e7f43b676 -r 86c7a023400e pkg/octree/loader.go --- a/pkg/octree/loader.go Mon Feb 25 16:16:33 2019 +0100 +++ b/pkg/octree/loader.go Mon Feb 25 17:02:33 2019 +0100 @@ -111,7 +111,7 @@ return tree, nil } -func deserialize(data []byte) (*Tree, error) { +func Deserialize(data []byte) (*Tree, error) { return loadReader( bufio.NewReader( snappy.NewReader(