package cache import ( "fmt" "os" "path/filepath" "time" "gitlink.org.cn/cloudream/common/pkgs/logger" cdssdk "gitlink.org.cn/cloudream/common/sdks/storage" "gitlink.org.cn/cloudream/common/utils/lo2" "gitlink.org.cn/cloudream/storage/client2/internal/mount/fuse" "gitlink.org.cn/cloudream/storage/common/pkgs/db2" "gitlink.org.cn/cloudream/storage/common/pkgs/downloader" ) type CacheEntry interface { fuse.FsEntry // 在虚拟文件系统中的路径,即不包含缓存目录的路径 PathComps() []string // 不再使用本缓存条目 // Release() } type CacheEntryInfo struct { PathComps []string Size int64 Mode os.FileMode ModTime time.Time IsDir bool } type Cache struct { db *db2.DB downloader *downloader.Downloader cacheDataDir string cacheMetaDir string } func NewCache(db *db2.DB, downloader *downloader.Downloader, cacheDataDir, cacheMetaDir string) *Cache { return &Cache{ db: db, downloader: downloader, cacheDataDir: cacheDataDir, cacheMetaDir: cacheMetaDir, } } func (c *Cache) GetCacheDataPath(comps ...string) string { comps2 := make([]string, len(comps)+1) comps2[0] = c.cacheDataDir copy(comps2[1:], comps) return filepath.Join(comps2...) } func (c *Cache) GetCacheDataPathComps(comps ...string) []string { comps2 := make([]string, len(comps)+1) comps2[0] = c.cacheDataDir copy(comps2[1:], comps) return comps2 } func (c *Cache) GetCacheMetaPath(comps ...string) string { comps2 := make([]string, len(comps)+1) comps2[0] = c.cacheMetaDir copy(comps2[1:], comps) return filepath.Join(comps2...) } func (c *Cache) GetCacheMetaPathComps(comps ...string) []string { comps2 := make([]string, len(comps)+1) comps2[0] = c.cacheMetaDir copy(comps2[1:], comps) return comps2 } // 获取指定位置的缓存条目信息。如果路径不存在,则返回nil。 func (c *Cache) Stat(pathComps []string) *CacheEntryInfo { metaPath := c.GetCacheMetaPath(pathComps...) stat, err := os.Stat(metaPath) if err != nil { // TODO 日志记录 return nil } if stat.IsDir() { info, err := loadCacheDirInfo(c, pathComps) if err != nil { return nil } return info } info, err := loadCacheFileInfo(c, pathComps) if err != nil { return nil } return info } // 创建一个缓存文件。如果文件已经存在,则会覆盖已有文件。如果加载过程中发生了错误,或者目标位置是一个目录,则会返回nil。 func (c *Cache) CreateFile(pathComps []string) *CacheFile { ch, err := createNewCacheFile(c, pathComps) if err != nil { // TODO 日志记录 return nil } return ch } // 尝试加载缓存文件,如果文件不存在,则使用obj的信息创建一个新缓存文件,而如果obj为nil,那么会返回nil。 func (c *Cache) LoadFile(pathComps []string, obj *cdssdk.Object) *CacheFile { ch, err := loadCacheFile(c, pathComps) if err == nil { ch.remoteObj = obj return ch } if !os.IsNotExist(err) { // TODO 日志记录 logger.Tracef("load cache file: %v", err) return nil } if obj == nil { return nil } ch, err = makeCacheFileFromObject(c, pathComps, obj) if err != nil { // TODO 日志记录 logger.Tracef("make cache file from object: %v", err) return nil } return ch } // 创建一个缓存目录。如果目录已经存在,则会重置目录属性。如果加载过程中发生了错误,或者目标位置是一个文件,则会返回nil func (c *Cache) CreateDir(pathComps []string) *CacheDir { ch, err := createNewCacheDir(c, pathComps) if err != nil { // TODO 日志记录 return nil } return ch } type CreateDirOption struct { ModTime time.Time } // 加载指定缓存目录,如果目录不存在,则使用createOpt选项创建目录,而如果createOpt为nil,那么会返回nil。 func (c *Cache) LoadDir(pathComps []string, createOpt *CreateDirOption) *CacheDir { ch, err := loadCacheDir(c, pathComps) if err == nil { return ch } if !os.IsNotExist(err) { // TODO 日志记录 return nil } if createOpt == nil { return nil } // 创建目录 ch, err = makeCacheDirFromOption(c, pathComps, *createOpt) if err != nil { // TODO 日志记录 return nil } return ch } // 加载指定路径下的所有缓存条目信息 func (c *Cache) StatMany(pathComps []string) []CacheEntryInfo { osEns, err := os.ReadDir(c.GetCacheMetaPath(pathComps...)) if err != nil { return nil } var infos []CacheEntryInfo for _, e := range osEns { if e.IsDir() { info, err := loadCacheDirInfo(c, append(lo2.ArrayClone(pathComps), e.Name())) if err != nil { continue } infos = append(infos, *info) } else { info, err := loadCacheFileInfo(c, append(lo2.ArrayClone(pathComps), e.Name())) if err != nil { continue } infos = append(infos, *info) } } return infos } // 删除指定路径的缓存文件或目录。删除目录时如果目录不为空,则会报错。 func (c *Cache) Remove(pathComps []string) error { return fmt.Errorf("not implemented") } // 移动指定路径的缓存文件或目录到新的路径。如果目标路径已经存在,则会报错。 // // 如果移动成功,则返回移动后的缓存文件或目录。如果文件或目录不存在,则返回nil。 func (c *Cache) Move(pathComps []string, newPathComps []string) (CacheEntry, error) { return nil, fmt.Errorf("not implemented") }