lib/fs: Consider options in case-fs caching (fixes #7371) (#7381)

This commit is contained in:
Simon Frei 2021-02-19 11:06:25 +01:00 committed by Jakob Borg
parent b0cce98648
commit 9be6f1a70e
4 changed files with 37 additions and 15 deletions

View File

@ -50,7 +50,7 @@ func (f FolderConfiguration) Filesystem() fs.Filesystem {
} }
filesystem := fs.NewFilesystem(f.FilesystemType, f.Path, opts...) filesystem := fs.NewFilesystem(f.FilesystemType, f.Path, opts...)
if !f.CaseSensitiveFS { if !f.CaseSensitiveFS {
filesystem = fs.NewCaseFilesystem(filesystem) filesystem = fs.NewCaseFilesystem(filesystem, opts...)
} }
return filesystem return filesystem
} }

View File

@ -27,12 +27,15 @@ var (
) )
func WithJunctionsAsDirs() Option { func WithJunctionsAsDirs() Option {
return func(fs Filesystem) { return Option{
apply: func(fs Filesystem) {
if basic, ok := fs.(*BasicFilesystem); !ok { if basic, ok := fs.(*BasicFilesystem); !ok {
l.Warnln("WithJunctionsAsDirs must only be used with FilesystemTypeBasic") l.Warnln("WithJunctionsAsDirs must only be used with FilesystemTypeBasic")
} else { } else {
basic.junctionsAsDirs = true basic.junctionsAsDirs = true
} }
},
id: "junctionsAsDirs",
} }
} }
@ -82,7 +85,7 @@ func newBasicFilesystem(root string, opts ...Option) *BasicFilesystem {
root: root, root: root,
} }
for _, opt := range opts { for _, opt := range opts {
opt(fs) opt.apply(fs)
} }
return fs return fs
} }

View File

@ -44,7 +44,7 @@ type realCaser interface {
type fskey struct { type fskey struct {
fstype FilesystemType fstype FilesystemType
uri string uri, opts string
} }
// caseFilesystemRegistry caches caseFilesystems and runs a routine to drop // caseFilesystemRegistry caches caseFilesystems and runs a routine to drop
@ -55,8 +55,22 @@ type caseFilesystemRegistry struct {
startCleaner sync.Once startCleaner sync.Once
} }
func (r *caseFilesystemRegistry) get(fs Filesystem) Filesystem { func newFSKey(fs Filesystem, opts ...Option) fskey {
k := fskey{fs.Type(), fs.URI()} k := fskey{
fstype: fs.Type(),
uri: fs.URI(),
}
if len(opts) > 0 {
k.opts = opts[0].id
for _, o := range opts[1:] {
k.opts += "&" + o.id
}
}
return k
}
func (r *caseFilesystemRegistry) get(fs Filesystem, opts ...Option) Filesystem {
k := newFSKey(fs, opts...)
// Use double locking when getting a caseFs. In the common case it will // Use double locking when getting a caseFs. In the common case it will
// already exist and we take the read lock fast path. If it doesn't, we // already exist and we take the read lock fast path. If it doesn't, we
@ -122,8 +136,10 @@ type caseFilesystem struct {
// from the real path. It is safe to use with any filesystem, i.e. also a // from the real path. It is safe to use with any filesystem, i.e. also a
// case-sensitive one. However it will add some overhead and thus shouldn't be // case-sensitive one. However it will add some overhead and thus shouldn't be
// used if the filesystem is known to already behave case-sensitively. // used if the filesystem is known to already behave case-sensitively.
func NewCaseFilesystem(fs Filesystem) Filesystem { func NewCaseFilesystem(fs Filesystem, opts ...Option) Filesystem {
return wrapFilesystem(fs, globalCaseFilesystemRegistry.get) return wrapFilesystem(fs, func(fs Filesystem) Filesystem {
return globalCaseFilesystemRegistry.get(fs, opts...)
})
} }
func (f *caseFilesystem) Chmod(name string, mode FileMode) error { func (f *caseFilesystem) Chmod(name string, mode FileMode) error {

View File

@ -178,7 +178,10 @@ var IsPermission = os.IsPermission
// IsPathSeparator is the equivalent of os.IsPathSeparator // IsPathSeparator is the equivalent of os.IsPathSeparator
var IsPathSeparator = os.IsPathSeparator var IsPathSeparator = os.IsPathSeparator
type Option func(Filesystem) type Option struct {
apply func(Filesystem)
id string
}
func NewFilesystem(fsType FilesystemType, uri string, opts ...Option) Filesystem { func NewFilesystem(fsType FilesystemType, uri string, opts ...Option) Filesystem {
var fs Filesystem var fs Filesystem