mirror of
https://github.com/tailscale/tailscale.git
synced 2025-02-27 18:57:35 +00:00
tailfs: improve doc comments for compositefs
Updates tailscale/corp#16827 Signed-off-by: Percy Wegmann <percy@tailscale.com>
This commit is contained in:
parent
f3d26c6c65
commit
ee971d3cc6
@ -1,7 +1,8 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
// Package compositefs provides a webdav.FileSystem that is composi
|
// Package compositefs provides a webdav.FileSystem that combines multiple
|
||||||
|
// child webdav.FileSystems. See [FS] for details.
|
||||||
package compositefs
|
package compositefs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -20,7 +21,7 @@ import (
|
|||||||
"tailscale.com/types/logger"
|
"tailscale.com/types/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Child is a child filesystem of a CompositeFileSystem
|
// Child is a child filesystem of an FS.
|
||||||
type Child struct {
|
type Child struct {
|
||||||
// Name is the name of the child
|
// Name is the name of the child
|
||||||
Name string
|
Name string
|
||||||
@ -38,26 +39,26 @@ func (c *Child) isAvailable() bool {
|
|||||||
return c.Available()
|
return c.Available()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Options specifies options for configuring a CompositeFileSystem.
|
// Options specifies options for configuring an FS.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
// Logf specifies a logging function to use
|
// Logf specifies a logging function to use
|
||||||
Logf logger.Logf
|
Logf logger.Logf
|
||||||
// StatChildren, if true, causes the CompositeFileSystem to stat its child
|
// StatChildren, if true, causes the FS to stat its child folders when
|
||||||
// folders when generating a root directory listing. This gives more
|
// generating a root directory listing. This gives more accurate
|
||||||
// accurate information but increases latency.
|
// information but increases latency.
|
||||||
StatChildren bool
|
StatChildren bool
|
||||||
// Clock, if specified, determines the current time. If not specified, we
|
// Clock, if specified, determines the current time. If not specified, we
|
||||||
// default to time.Now().
|
// default to time.Now().
|
||||||
Clock tstime.Clock
|
Clock tstime.Clock
|
||||||
}
|
}
|
||||||
|
|
||||||
// New constructs a CompositeFileSystem that logs using the given logf.
|
// New constructs an FS that logs using the given logf.
|
||||||
func New(opts Options) *CompositeFileSystem {
|
func New(opts Options) *FS {
|
||||||
logf := opts.Logf
|
logf := opts.Logf
|
||||||
if logf == nil {
|
if logf == nil {
|
||||||
logf = log.Printf
|
logf = log.Printf
|
||||||
}
|
}
|
||||||
fs := &CompositeFileSystem{
|
fs := &FS{
|
||||||
logf: logf,
|
logf: logf,
|
||||||
statChildren: opts.StatChildren,
|
statChildren: opts.StatChildren,
|
||||||
}
|
}
|
||||||
@ -69,20 +70,20 @@ func New(opts Options) *CompositeFileSystem {
|
|||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompositeFileSystem is a webdav.FileSystem that is composed of multiple
|
// FS is a webdav.FileSystem that is composed of multiple child
|
||||||
// child webdav.FileSystems. Each child is identified by a name and appears
|
// webdav.FileSystems. Each child is identified by a name and appears
|
||||||
// as a folder within the root of the CompositeFileSystem, with the children
|
// as a folder within the root of the FS, with the children
|
||||||
// sorted lexicographically by name.
|
// sorted lexicographically by name.
|
||||||
//
|
//
|
||||||
// Children in a CompositeFileSystem can only be added or removed via calls to
|
// Children in an FS can only be added or removed via calls to
|
||||||
// the AddChild and RemoveChild methods, they cannot be added via operations
|
// the AddChild and RemoveChild methods, they cannot be added via operations
|
||||||
// on the webdav.FileSystem interface like filesystem.Mkdir or filesystem.OpenFile.
|
// on the webdav.FileSystem interface like filesystem.Mkdir or filesystem.OpenFile.
|
||||||
// In other words, the root of the CompositeFileSystem acts as read-only, not
|
// In other words, the root of the FS acts as read-only, not
|
||||||
// permitting the addition, removal or renaming of folders.
|
// permitting the addition, removal or renaming of folders.
|
||||||
//
|
//
|
||||||
// Rename is only supported within a single child. Renaming across children
|
// Rename is only supported within a single child. Renaming across children
|
||||||
// is not supported, as it wouldn't be possible to perform it atomically.
|
// is not supported, as it wouldn't be possible to perform it atomically.
|
||||||
type CompositeFileSystem struct {
|
type FS struct {
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
statChildren bool
|
statChildren bool
|
||||||
now func() time.Time
|
now func() time.Time
|
||||||
@ -94,7 +95,7 @@ type CompositeFileSystem struct {
|
|||||||
|
|
||||||
// AddChild ads a single child with the given name, replacing any existing
|
// AddChild ads a single child with the given name, replacing any existing
|
||||||
// child with the same name.
|
// child with the same name.
|
||||||
func (cfs *CompositeFileSystem) AddChild(child *Child) {
|
func (cfs *FS) AddChild(child *Child) {
|
||||||
cfs.childrenMu.Lock()
|
cfs.childrenMu.Lock()
|
||||||
oldIdx, oldChild := cfs.findChildLocked(child.Name)
|
oldIdx, oldChild := cfs.findChildLocked(child.Name)
|
||||||
if oldChild != nil {
|
if oldChild != nil {
|
||||||
@ -116,7 +117,7 @@ func (cfs *CompositeFileSystem) AddChild(child *Child) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RemoveChild removes the child with the given name, if it exists.
|
// RemoveChild removes the child with the given name, if it exists.
|
||||||
func (cfs *CompositeFileSystem) RemoveChild(name string) {
|
func (cfs *FS) RemoveChild(name string) {
|
||||||
cfs.childrenMu.Lock()
|
cfs.childrenMu.Lock()
|
||||||
oldPos, oldChild := cfs.findChildLocked(name)
|
oldPos, oldChild := cfs.findChildLocked(name)
|
||||||
if oldChild != nil {
|
if oldChild != nil {
|
||||||
@ -139,7 +140,7 @@ func (cfs *CompositeFileSystem) RemoveChild(name string) {
|
|||||||
|
|
||||||
// SetChildren replaces the entire existing set of children with the given
|
// SetChildren replaces the entire existing set of children with the given
|
||||||
// ones.
|
// ones.
|
||||||
func (cfs *CompositeFileSystem) SetChildren(children ...*Child) {
|
func (cfs *FS) SetChildren(children ...*Child) {
|
||||||
slices.SortFunc(children, func(a, b *Child) int {
|
slices.SortFunc(children, func(a, b *Child) int {
|
||||||
return strings.Compare(a.Name, b.Name)
|
return strings.Compare(a.Name, b.Name)
|
||||||
})
|
})
|
||||||
@ -159,7 +160,7 @@ func (cfs *CompositeFileSystem) SetChildren(children ...*Child) {
|
|||||||
|
|
||||||
// GetChild returns the child with the given name and a boolean indicating
|
// GetChild returns the child with the given name and a boolean indicating
|
||||||
// whether or not it was found.
|
// whether or not it was found.
|
||||||
func (cfs *CompositeFileSystem) GetChild(name string) (webdav.FileSystem, bool) {
|
func (cfs *FS) GetChild(name string) (webdav.FileSystem, bool) {
|
||||||
_, child := cfs.findChildLocked(name)
|
_, child := cfs.findChildLocked(name)
|
||||||
if child == nil {
|
if child == nil {
|
||||||
return nil, false
|
return nil, false
|
||||||
@ -167,7 +168,7 @@ func (cfs *CompositeFileSystem) GetChild(name string) (webdav.FileSystem, bool)
|
|||||||
return child.FS, true
|
return child.FS, true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfs *CompositeFileSystem) findChildLocked(name string) (int, *Child) {
|
func (cfs *FS) findChildLocked(name string) (int, *Child) {
|
||||||
var child *Child
|
var child *Child
|
||||||
i, found := slices.BinarySearchFunc(cfs.children, name, func(child *Child, name string) int {
|
i, found := slices.BinarySearchFunc(cfs.children, name, func(child *Child, name string) int {
|
||||||
return strings.Compare(child.Name, name)
|
return strings.Compare(child.Name, name)
|
||||||
@ -179,10 +180,10 @@ func (cfs *CompositeFileSystem) findChildLocked(name string) (int, *Child) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// pathInfoFor returns a pathInfo for the given filename. If the filename
|
// pathInfoFor returns a pathInfo for the given filename. If the filename
|
||||||
// refers to a Child that does not exist within this CompositeFileSystem,
|
// refers to a Child that does not exist within this FS, it will return the
|
||||||
// it will return the error os.ErrNotExist. Even when returning an error,
|
// error os.ErrNotExist. Even when returning an error, it will still return
|
||||||
// it will still return a complete pathInfo.
|
// a complete pathInfo.
|
||||||
func (cfs *CompositeFileSystem) pathInfoFor(name string) (pathInfo, error) {
|
func (cfs *FS) pathInfoFor(name string) (pathInfo, error) {
|
||||||
cfs.childrenMu.Lock()
|
cfs.childrenMu.Lock()
|
||||||
defer cfs.childrenMu.Unlock()
|
defer cfs.childrenMu.Unlock()
|
||||||
|
|
||||||
@ -211,7 +212,7 @@ type pathInfo struct {
|
|||||||
pathOnChild string
|
pathOnChild string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfs *CompositeFileSystem) Close() error {
|
func (cfs *FS) Close() error {
|
||||||
cfs.childrenMu.Lock()
|
cfs.childrenMu.Lock()
|
||||||
children := cfs.children
|
children := cfs.children
|
||||||
cfs.childrenMu.Unlock()
|
cfs.childrenMu.Unlock()
|
||||||
|
@ -14,7 +14,7 @@ import (
|
|||||||
// read-only, so any attempts to make directories within the root will fail
|
// read-only, so any attempts to make directories within the root will fail
|
||||||
// with os.ErrPermission. Attempts to make directories within one of the child
|
// with os.ErrPermission. Attempts to make directories within one of the child
|
||||||
// filesystems will be handled by the respective child.
|
// filesystems will be handled by the respective child.
|
||||||
func (cfs *CompositeFileSystem) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
|
func (cfs *FS) Mkdir(ctx context.Context, name string, perm os.FileMode) error {
|
||||||
if shared.IsRoot(name) {
|
if shared.IsRoot(name) {
|
||||||
// root directory already exists, consider this okay
|
// root directory already exists, consider this okay
|
||||||
return nil
|
return nil
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// OpenFile implements interface webdav.Filesystem.
|
// OpenFile implements interface webdav.Filesystem.
|
||||||
func (cfs *CompositeFileSystem) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
|
func (cfs *FS) OpenFile(ctx context.Context, name string, flag int, perm os.FileMode) (webdav.File, error) {
|
||||||
if !shared.IsRoot(name) {
|
if !shared.IsRoot(name) {
|
||||||
pathInfo, err := cfs.pathInfoFor(name)
|
pathInfo, err := cfs.pathInfoFor(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
// RemoveAll implements webdav.File. The root of this file system is read-only,
|
// RemoveAll implements webdav.File. The root of this file system is read-only,
|
||||||
// so attempting to call RemoveAll on the root will fail with os.ErrPermission.
|
// so attempting to call RemoveAll on the root will fail with os.ErrPermission.
|
||||||
// RemoveAll within a child will be handled by the respective child.
|
// RemoveAll within a child will be handled by the respective child.
|
||||||
func (cfs *CompositeFileSystem) RemoveAll(ctx context.Context, name string) error {
|
func (cfs *FS) RemoveAll(ctx context.Context, name string) error {
|
||||||
if shared.IsRoot(name) {
|
if shared.IsRoot(name) {
|
||||||
// root directory is read-only
|
// root directory is read-only
|
||||||
return os.ErrPermission
|
return os.ErrPermission
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
// filesystem will fail with os.ErrPermission. Renaming across children is not
|
// filesystem will fail with os.ErrPermission. Renaming across children is not
|
||||||
// supported and will fail with os.ErrPermission. Renaming within a child will
|
// supported and will fail with os.ErrPermission. Renaming within a child will
|
||||||
// be handled by the respective child.
|
// be handled by the respective child.
|
||||||
func (cfs *CompositeFileSystem) Rename(ctx context.Context, oldName, newName string) error {
|
func (cfs *FS) Rename(ctx context.Context, oldName, newName string) error {
|
||||||
if shared.IsRoot(oldName) || shared.IsRoot(newName) {
|
if shared.IsRoot(oldName) || shared.IsRoot(newName) {
|
||||||
// root directory is read-only
|
// root directory is read-only
|
||||||
return os.ErrPermission
|
return os.ErrPermission
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Stat implements webdav.FileSystem.
|
// Stat implements webdav.FileSystem.
|
||||||
func (cfs *CompositeFileSystem) Stat(ctx context.Context, name string) (fs.FileInfo, error) {
|
func (cfs *FS) Stat(ctx context.Context, name string) (fs.FileInfo, error) {
|
||||||
if shared.IsRoot(name) {
|
if shared.IsRoot(name) {
|
||||||
// Root is a directory
|
// Root is a directory
|
||||||
// always use now() as the modified time to bust caches
|
// always use now() as the modified time to bust caches
|
||||||
|
@ -44,7 +44,7 @@ func NewFileSystemForLocal(logf logger.Logf) *FileSystemForLocal {
|
|||||||
// provides a unified WebDAV interface to remote TailFS shares on other nodes.
|
// provides a unified WebDAV interface to remote TailFS shares on other nodes.
|
||||||
type FileSystemForLocal struct {
|
type FileSystemForLocal struct {
|
||||||
logf logger.Logf
|
logf logger.Logf
|
||||||
cfs *compositefs.CompositeFileSystem
|
cfs *compositefs.FS
|
||||||
listener *connListener
|
listener *connListener
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +93,7 @@ func (s *FileSystemForLocal) SetRemotes(domain string, remotes []*tailfs.Remote,
|
|||||||
domainChild = compositefs.New(compositefs.Options{Logf: s.logf})
|
domainChild = compositefs.New(compositefs.Options{Logf: s.logf})
|
||||||
s.cfs.SetChildren(&compositefs.Child{Name: domain, FS: domainChild})
|
s.cfs.SetChildren(&compositefs.Child{Name: domain, FS: domainChild})
|
||||||
}
|
}
|
||||||
domainChild.(*compositefs.CompositeFileSystem).SetChildren(children...)
|
domainChild.(*compositefs.FS).SetChildren(children...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close() stops serving the WebDAV content
|
// Close() stops serving the WebDAV content
|
||||||
|
@ -59,8 +59,8 @@ type webdavFS struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New creates a new webdav.FileSystem backed by the given gowebdav.Client.
|
// New creates a new webdav.FileSystem backed by the given gowebdav.Client.
|
||||||
// If cacheTTL is greater than zero, the filesystem will cache results from
|
// If [opts.StatCacheTTL] is greater than zero, the filesystem will cache
|
||||||
// Stat calls for the given duration.
|
// results from Stat calls for the given duration.
|
||||||
func New(opts Options) webdav.FileSystem {
|
func New(opts Options) webdav.FileSystem {
|
||||||
if opts.Logf == nil {
|
if opts.Logf == nil {
|
||||||
opts.Logf = log.Printf
|
opts.Logf = log.Printf
|
||||||
|
Loading…
x
Reference in New Issue
Block a user