Fix deadlock at container finish.
[lightning.git] / flake.go
1 // Copyright (C) The Lightning Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package lightning
6
7 import (
8         "context"
9         "flag"
10         "fmt"
11         "io"
12         "net/http"
13         _ "net/http/pprof"
14
15         "git.arvados.org/arvados.git/sdk/go/arvados"
16         log "github.com/sirupsen/logrus"
17 )
18
19 type flakecmd struct {
20         filter filter
21 }
22
23 func (cmd *flakecmd) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
24         var err error
25         defer func() {
26                 if err != nil {
27                         fmt.Fprintf(stderr, "%s\n", err)
28                 }
29         }()
30         flags := flag.NewFlagSet("", flag.ContinueOnError)
31         flags.SetOutput(stderr)
32         pprof := flags.String("pprof", "", "serve Go profile data at http://`[addr]:port`")
33         runlocal := flags.Bool("local", false, "run on local host (default: run in an arvados container)")
34         projectUUID := flags.String("project", "", "project `UUID` for output data")
35         priority := flags.Int("priority", 500, "container request priority")
36         inputDir := flags.String("input-dir", "./in", "input `directory`")
37         outputDir := flags.String("output-dir", "./out", "output `directory`")
38         cmd.filter.Flags(flags)
39         err = flags.Parse(args)
40         if err == flag.ErrHelp {
41                 err = nil
42                 return 0
43         } else if err != nil {
44                 return 2
45         }
46
47         if *pprof != "" {
48                 go func() {
49                         log.Println(http.ListenAndServe(*pprof, nil))
50                 }()
51         }
52
53         if !*runlocal {
54                 runner := arvadosContainerRunner{
55                         Name:        "lightning flake",
56                         Client:      arvados.NewClientFromEnv(),
57                         ProjectUUID: *projectUUID,
58                         RAM:         700000000000,
59                         VCPUs:       96,
60                         Priority:    *priority,
61                         KeepCache:   2,
62                         APIAccess:   true,
63                 }
64                 err = runner.TranslatePaths(inputDir)
65                 if err != nil {
66                         return 1
67                 }
68                 runner.Args = []string{"flake", "-local=true",
69                         "-pprof", ":6060",
70                         "-input-dir", *inputDir,
71                         "-output-dir", "/mnt/output",
72                         "-max-variants", fmt.Sprintf("%d", cmd.filter.MaxVariants),
73                         "-min-coverage", fmt.Sprintf("%f", cmd.filter.MinCoverage),
74                         "-max-tag", fmt.Sprintf("%d", cmd.filter.MaxTag),
75                 }
76                 var output string
77                 output, err = runner.Run()
78                 if err != nil {
79                         return 1
80                 }
81                 fmt.Fprintln(stdout, output)
82                 return 0
83         }
84
85         tilelib := &tileLibrary{
86                 retainNoCalls:       true,
87                 retainTileSequences: true,
88                 compactGenomes:      map[string][]tileVariantID{},
89         }
90         err = tilelib.LoadDir(context.Background(), *inputDir)
91         if err != nil {
92                 return 1
93         }
94
95         log.Info("filtering")
96         cmd.filter.Apply(tilelib)
97         log.Info("tidying")
98         tilelib.Tidy()
99         err = tilelib.WriteDir(*outputDir)
100         if err != nil {
101                 return 1
102         }
103         return 0
104 }