2019-05-23 11:26:16 +00:00
|
|
|
// Package cache implements the Fs cache
|
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
2020-05-01 11:49:34 +00:00
|
|
|
"sync"
|
|
|
|
|
2019-07-28 17:47:38 +00:00
|
|
|
"github.com/rclone/rclone/fs"
|
2019-07-31 21:19:07 +00:00
|
|
|
"github.com/rclone/rclone/lib/cache"
|
2019-05-23 11:26:16 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2020-05-01 11:49:34 +00:00
|
|
|
c = cache.New()
|
|
|
|
mu sync.Mutex // mutex to protect remap
|
|
|
|
remap = map[string]string{} // map user supplied names to canonical names
|
2019-05-23 11:26:16 +00:00
|
|
|
)
|
|
|
|
|
2020-06-15 13:02:04 +00:00
|
|
|
// Canonicalize looks up fsString in the mapping from user supplied
|
|
|
|
// names to canonical names and return the canonical form
|
|
|
|
func Canonicalize(fsString string) string {
|
2020-05-01 11:49:34 +00:00
|
|
|
mu.Lock()
|
|
|
|
canonicalName, ok := remap[fsString]
|
|
|
|
mu.Unlock()
|
|
|
|
if !ok {
|
|
|
|
return fsString
|
|
|
|
}
|
|
|
|
fs.Debugf(nil, "fs cache: switching user supplied name %q for canonical name %q", fsString, canonicalName)
|
|
|
|
return canonicalName
|
|
|
|
}
|
|
|
|
|
|
|
|
// Put in a mapping from fsString => canonicalName if they are different
|
|
|
|
func addMapping(fsString, canonicalName string) {
|
|
|
|
if canonicalName == fsString {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
mu.Lock()
|
|
|
|
remap[fsString] = canonicalName
|
|
|
|
mu.Unlock()
|
|
|
|
}
|
|
|
|
|
2020-05-20 10:39:20 +00:00
|
|
|
// GetFn gets an fs.Fs named fsString either from the cache or creates
|
2019-07-31 21:19:07 +00:00
|
|
|
// it afresh with the create function
|
|
|
|
func GetFn(fsString string, create func(fsString string) (fs.Fs, error)) (f fs.Fs, err error) {
|
2020-06-15 13:02:04 +00:00
|
|
|
fsString = Canonicalize(fsString)
|
2020-05-01 11:49:34 +00:00
|
|
|
created := false
|
2019-08-09 21:19:41 +00:00
|
|
|
value, err := c.Get(fsString, func(fsString string) (f interface{}, ok bool, err error) {
|
|
|
|
f, err = create(fsString)
|
2019-07-31 21:19:07 +00:00
|
|
|
ok = err == nil || err == fs.ErrorIsFile
|
2020-05-01 11:49:34 +00:00
|
|
|
created = ok
|
2019-07-31 21:19:07 +00:00
|
|
|
return f, ok, err
|
|
|
|
})
|
2019-08-09 21:19:41 +00:00
|
|
|
if err != nil && err != fs.ErrorIsFile {
|
2019-07-31 21:19:07 +00:00
|
|
|
return nil, err
|
|
|
|
}
|
2020-05-01 11:49:34 +00:00
|
|
|
f = value.(fs.Fs)
|
|
|
|
// Check we stored the Fs at the canonical name
|
|
|
|
if created {
|
|
|
|
canonicalName := fs.ConfigString(f)
|
|
|
|
if canonicalName != fsString {
|
2020-07-02 09:15:47 +00:00
|
|
|
// Note that if err == fs.ErrorIsFile at this moment
|
|
|
|
// then we can't rename the remote as it will have the
|
|
|
|
// wrong error status, we need to add a new one.
|
|
|
|
if err == nil {
|
|
|
|
fs.Debugf(nil, "fs cache: renaming cache item %q to be canonical %q", fsString, canonicalName)
|
|
|
|
value, found := c.Rename(fsString, canonicalName)
|
|
|
|
if found {
|
|
|
|
f = value.(fs.Fs)
|
|
|
|
}
|
|
|
|
addMapping(fsString, canonicalName)
|
|
|
|
} else {
|
|
|
|
fs.Debugf(nil, "fs cache: adding new entry for parent of %q, %q", fsString, canonicalName)
|
|
|
|
Put(canonicalName, f)
|
2020-05-01 11:49:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return f, err
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pin f into the cache until Unpin is called
|
|
|
|
func Pin(f fs.Fs) {
|
|
|
|
c.Pin(fs.ConfigString(f))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Unpin f from the cache
|
|
|
|
func Unpin(f fs.Fs) {
|
|
|
|
c.Pin(fs.ConfigString(f))
|
2019-05-23 11:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-05-20 10:39:20 +00:00
|
|
|
// Get gets an fs.Fs named fsString either from the cache or creates it afresh
|
2019-05-23 11:26:16 +00:00
|
|
|
func Get(fsString string) (f fs.Fs, err error) {
|
2019-07-31 21:19:07 +00:00
|
|
|
return GetFn(fsString, fs.NewFs)
|
2019-05-23 11:26:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Put puts an fs.Fs named fsString into the cache
|
|
|
|
func Put(fsString string, f fs.Fs) {
|
2020-05-01 11:49:34 +00:00
|
|
|
canonicalName := fs.ConfigString(f)
|
|
|
|
c.Put(canonicalName, f)
|
|
|
|
addMapping(fsString, canonicalName)
|
2019-05-23 11:26:16 +00:00
|
|
|
}
|
|
|
|
|
2020-05-20 10:39:20 +00:00
|
|
|
// Clear removes everything from the cache
|
2019-05-23 11:26:16 +00:00
|
|
|
func Clear() {
|
2019-07-31 21:19:07 +00:00
|
|
|
c.Clear()
|
2019-05-23 11:26:16 +00:00
|
|
|
}
|