1package record
2
3import (
4	"context"
5	"sync"
6	"time"
7
8	"bazil.org/fuse"
9	"bazil.org/fuse/fs"
10)
11
12type nothing struct{}
13
14// ReleaseWaiter notes whether a FUSE Release call has been seen.
15//
16// Releases are not guaranteed to happen synchronously with any client
17// call, so they must be waited for.
18type ReleaseWaiter struct {
19	once sync.Once
20	seen chan nothing
21}
22
23var _ = fs.HandleReleaser(&ReleaseWaiter{})
24
25func (r *ReleaseWaiter) init() {
26	r.once.Do(func() {
27		r.seen = make(chan nothing, 1)
28	})
29}
30
31func (r *ReleaseWaiter) Release(ctx context.Context, req *fuse.ReleaseRequest) error {
32	r.init()
33	close(r.seen)
34	return nil
35}
36
37// WaitForRelease waits for Release to be called.
38//
39// With zero duration, wait forever. Otherwise, timeout early
40// in a more controlled way than `-test.timeout`.
41//
42// Returns whether a Release was seen. Always true if dur==0.
43func (r *ReleaseWaiter) WaitForRelease(dur time.Duration) bool {
44	r.init()
45	var timeout <-chan time.Time
46	if dur > 0 {
47		timeout = time.After(dur)
48	}
49	select {
50	case <-r.seen:
51		return true
52	case <-timeout:
53		return false
54	}
55}
56