Files
rclone/vfs/nodeaux.go
T
Nick Craig-Wood b6ffdfa8e6 vfs: rename aux.go to nodeaux.go as aux is a reserved file name on Windows
This commit introduced aux.go which unfortunately is illegal on windows.

e006d7c13f vfs: fix crash when multiple mounts or servers share the same VFS

Rename aux_test.go too to keep the pair together.
2026-07-27 16:35:08 +01:00

86 lines
2.3 KiB
Go

package vfs
import "sync/atomic"
// auxEntry associates an owner with a value attached to a node.
type auxEntry struct {
owner, value any
}
// aux holds auxiliary values attached to a node, keyed by owner.
//
// It is embedded in Dir and File to provide the Aux, SetAux, Sys and
// SetSys methods of the Node interface.
//
// Reads are lock free. Writes copy the entry list, which is assumed
// to be very short.
type aux struct {
entries atomic.Pointer[[]auxEntry]
}
// sysOwner is the owner Sys and SetSys attach their value under.
type sysOwner struct{}
// Aux returns the value attached to the node for owner, or nil if
// none is attached.
func (a *aux) Aux(owner any) any {
if entries := a.entries.Load(); entries != nil {
for _, entry := range *entries {
if entry.owner == owner {
return entry.value
}
}
}
return nil
}
// SetAux attaches value to the node for owner, replacing any value
// owner attached before. Attaching nil removes owner's value.
//
// Values attached by different owners are independent, so multiple
// users of a shared VFS do not conflict. Owner must be comparable and
// unique to the user - a pointer to the user's filesystem struct is a
// good choice.
func (a *aux) SetAux(owner, value any) {
for {
old := a.entries.Load()
var entries []auxEntry
if old != nil {
entries = make([]auxEntry, 0, len(*old)+1)
for _, entry := range *old {
if entry.owner != owner {
entries = append(entries, entry)
}
}
}
if value != nil {
entries = append(entries, auxEntry{owner: owner, value: value})
}
var next *[]auxEntry
if len(entries) != 0 {
next = &entries
}
if a.entries.CompareAndSwap(old, next) {
return
}
}
}
// Sys returns the value set with SetSys (can be nil) - satisfies
// os.FileInfo.
//
// This is what callers reading the node through os.FileInfo (e.g. the
// NFS server library) will see. It is reserved for users which need
// to control that; users caching their own data on the node should
// use Aux and SetAux instead. As the VFS may be shared, the value
// stored here should be derived from the node alone so that all users
// store the same value.
func (a *aux) Sys() any {
return a.Aux(sysOwner{})
}
// SetSys sets the value returned by Sys - see Sys for the contract.
func (a *aux) SetSys(x any) {
a.SetAux(sysOwner{}, x)
}