aboutsummaryrefslogtreecommitdiffhomepage
path: root/cmd/mbf/cache.go
blob: 05fa7070b590f63640d44f79c3a0087e9309eb96 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package main

import (
	"context"
	"os"
	"path/filepath"
	"testing"

	"hakurei.app/check"
	"hakurei.app/internal/pkg"
	"hakurei.app/message"
)

// cache refers to an instance of [pkg.Cache] that might be open.
type cache struct {
	ctx context.Context
	msg message.Msg

	// Should generally not be used directly.
	c *pkg.Cache

	cures, jobs        int
	hostAbstract, idle bool
	verboseInit        bool

	base string
}

// open opens the underlying [pkg.Cache].
func (cache *cache) open() (err error) {
	if cache.c != nil {
		return os.ErrInvalid
	}

	var base *check.Absolute
	if cache.base, err = filepath.Abs(cache.base); err != nil {
		return
	} else if base, err = check.NewAbs(cache.base); err != nil {
		return
	}

	var flags int
	if cache.idle {
		flags |= pkg.CSchedIdle
	}
	if cache.hostAbstract {
		flags |= pkg.CHostAbstract
	}
	if !cache.verboseInit {
		flags |= pkg.CSuppressInit
	}

	done := make(chan struct{})
	defer close(done)
	go func() {
		select {
		case <-cache.ctx.Done():
			if testing.Testing() {
				return
			}
			os.Exit(2)

		case <-done:
			return
		}
	}()

	cache.msg.Verbosef("opening cache at %s", base)
	cache.c, err = pkg.Open(
		cache.ctx,
		cache.msg,
		flags,
		cache.cures,
		cache.jobs,
		base,
	)
	return
}

// Close closes the underlying [pkg.Cache] if it is open.
func (cache *cache) Close() {
	if cache.c != nil {
		cache.c.Close()
	}
}

// Do calls f on the underlying cache and returns its error value.
func (cache *cache) Do(f func(cache *pkg.Cache) error) error {
	if cache.c == nil {
		if err := cache.open(); err != nil {
			return err
		}
	}
	return f(cache.c)
}