Browse Source

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

Simon Frei 4 years ago
parent
commit
aa1c274231
4 changed files with 37 additions and 15 deletions
  1. 1 1
      lib/config/folderconfiguration.go
  2. 10 7
      lib/fs/basicfs.go
  3. 22 6
      lib/fs/casefs.go
  4. 4 1
      lib/fs/filesystem.go

+ 1 - 1
lib/config/folderconfiguration.go

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

+ 10 - 7
lib/fs/basicfs.go

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

+ 22 - 6
lib/fs/casefs.go

@@ -43,8 +43,8 @@ type realCaser interface {
 }
 
 type fskey struct {
-	fstype FilesystemType
-	uri    string
+	fstype    FilesystemType
+	uri, opts string
 }
 
 // caseFilesystemRegistry caches caseFilesystems and runs a routine to drop
@@ -55,8 +55,22 @@ type caseFilesystemRegistry struct {
 	startCleaner sync.Once
 }
 
-func (r *caseFilesystemRegistry) get(fs Filesystem) Filesystem {
-	k := fskey{fs.Type(), fs.URI()}
+func newFSKey(fs Filesystem, opts ...Option) fskey {
+	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
 	// 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
 // 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.
-func NewCaseFilesystem(fs Filesystem) Filesystem {
-	return wrapFilesystem(fs, globalCaseFilesystemRegistry.get)
+func NewCaseFilesystem(fs Filesystem, opts ...Option) Filesystem {
+	return wrapFilesystem(fs, func(fs Filesystem) Filesystem {
+		return globalCaseFilesystemRegistry.get(fs, opts...)
+	})
 }
 
 func (f *caseFilesystem) Chmod(name string, mode FileMode) error {

+ 4 - 1
lib/fs/filesystem.go

@@ -178,7 +178,10 @@ var IsPermission = os.IsPermission
 // IsPathSeparator is the equivalent of 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 {
 	var fs Filesystem