~kris/9p

llm9p

llm9p/internal/llmfs/session_ref.go -rw-r--r-- 1.6 KiB
cc50c152 — Kris Yotam docs: update repo URL to sr.ht 4 months ago
                                                                                
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
package llmfs

import (
	"sync"

	"github.com/NERVsystems/llm9p/internal/llm"
	"github.com/NERVsystems/llm9p/internal/protocol"
)

// sessionRefFile wraps a protocol.File and tracks a reference to its session.
// It calls sm.IncRef(id) on Open and sm.DecRef(id) on the first Close, so
// that sessions are automatically cleaned up when all their files are clunked.
type sessionRefFile struct {
	protocol.File
	sm     *llm.SessionManager
	id     int
	once   sync.Once
	opened bool
}

func (r *sessionRefFile) Open(mode uint8) error {
	err := r.File.Open(mode)
	if err == nil {
		r.opened = true
		r.sm.IncRef(r.id)
	}
	return err
}

func (r *sessionRefFile) Close() error {
	err := r.File.Close()
	if r.opened {
		r.once.Do(func() {
			r.sm.DecRef(r.id)
		})
	}
	return err
}

// sessionRefDir wraps a protocol.Dir (SessionDir) with the same ref counting.
// It additionally overrides Lookup so that child files are also ref-counted.
type sessionRefDir struct {
	protocol.Dir
	sm     *llm.SessionManager
	id     int
	once   sync.Once
	opened bool
}

func (r *sessionRefDir) Open(mode uint8) error {
	err := r.Dir.Open(mode)
	if err == nil {
		r.opened = true
		r.sm.IncRef(r.id)
	}
	return err
}

func (r *sessionRefDir) Close() error {
	err := r.Dir.Close()
	if r.opened {
		r.once.Do(func() {
			r.sm.DecRef(r.id)
		})
	}
	return err
}

// Lookup wraps child files in sessionRefFile so each open fid contributes
// its own reference to the session.
func (r *sessionRefDir) Lookup(name string) (protocol.File, error) {
	f, err := r.Dir.Lookup(name)
	if err != nil {
		return nil, err
	}
	return &sessionRefFile{File: f, sm: r.sm, id: r.id}, nil
}