You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

cache.go 5.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. package cache
  2. import (
  3. "fmt"
  4. "os"
  5. "path/filepath"
  6. "time"
  7. "gitlink.org.cn/cloudream/common/pkgs/logger"
  8. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  9. "gitlink.org.cn/cloudream/common/utils/lo2"
  10. "gitlink.org.cn/cloudream/storage/client2/internal/mount/fuse"
  11. "gitlink.org.cn/cloudream/storage/common/pkgs/db2"
  12. "gitlink.org.cn/cloudream/storage/common/pkgs/downloader"
  13. )
  14. type CacheEntry interface {
  15. fuse.FsEntry
  16. // 在虚拟文件系统中的路径,即不包含缓存目录的路径
  17. PathComps() []string
  18. // 不再使用本缓存条目
  19. // Release()
  20. }
  21. type CacheEntryInfo struct {
  22. PathComps []string
  23. Size int64
  24. Mode os.FileMode
  25. ModTime time.Time
  26. IsDir bool
  27. }
  28. type Cache struct {
  29. db *db2.DB
  30. downloader *downloader.Downloader
  31. cacheDataDir string
  32. cacheMetaDir string
  33. }
  34. func NewCache(db *db2.DB, downloader *downloader.Downloader, cacheDataDir, cacheMetaDir string) *Cache {
  35. return &Cache{
  36. db: db,
  37. downloader: downloader,
  38. cacheDataDir: cacheDataDir,
  39. cacheMetaDir: cacheMetaDir,
  40. }
  41. }
  42. func (c *Cache) GetCacheDataPath(comps ...string) string {
  43. comps2 := make([]string, len(comps)+1)
  44. comps2[0] = c.cacheDataDir
  45. copy(comps2[1:], comps)
  46. return filepath.Join(comps2...)
  47. }
  48. func (c *Cache) GetCacheDataPathComps(comps ...string) []string {
  49. comps2 := make([]string, len(comps)+1)
  50. comps2[0] = c.cacheDataDir
  51. copy(comps2[1:], comps)
  52. return comps2
  53. }
  54. func (c *Cache) GetCacheMetaPath(comps ...string) string {
  55. comps2 := make([]string, len(comps)+1)
  56. comps2[0] = c.cacheMetaDir
  57. copy(comps2[1:], comps)
  58. return filepath.Join(comps2...)
  59. }
  60. func (c *Cache) GetCacheMetaPathComps(comps ...string) []string {
  61. comps2 := make([]string, len(comps)+1)
  62. comps2[0] = c.cacheMetaDir
  63. copy(comps2[1:], comps)
  64. return comps2
  65. }
  66. // 获取指定位置的缓存条目信息。如果路径不存在,则返回nil。
  67. func (c *Cache) Stat(pathComps []string) *CacheEntryInfo {
  68. metaPath := c.GetCacheMetaPath(pathComps...)
  69. stat, err := os.Stat(metaPath)
  70. if err != nil {
  71. // TODO 日志记录
  72. return nil
  73. }
  74. if stat.IsDir() {
  75. info, err := loadCacheDirInfo(c, pathComps)
  76. if err != nil {
  77. return nil
  78. }
  79. return info
  80. }
  81. info, err := loadCacheFileInfo(c, pathComps)
  82. if err != nil {
  83. return nil
  84. }
  85. return info
  86. }
  87. // 创建一个缓存文件。如果文件已经存在,则会覆盖已有文件。如果加载过程中发生了错误,或者目标位置是一个目录,则会返回nil。
  88. func (c *Cache) CreateFile(pathComps []string) *CacheFile {
  89. ch, err := createNewCacheFile(c, pathComps)
  90. if err != nil {
  91. // TODO 日志记录
  92. return nil
  93. }
  94. return ch
  95. }
  96. // 尝试加载缓存文件,如果文件不存在,则使用obj的信息创建一个新缓存文件,而如果obj为nil,那么会返回nil。
  97. func (c *Cache) LoadFile(pathComps []string, obj *cdssdk.Object) *CacheFile {
  98. ch, err := loadCacheFile(c, pathComps)
  99. if err == nil {
  100. ch.remoteObj = obj
  101. return ch
  102. }
  103. if !os.IsNotExist(err) {
  104. // TODO 日志记录
  105. logger.Tracef("load cache file: %v", err)
  106. return nil
  107. }
  108. if obj == nil {
  109. return nil
  110. }
  111. ch, err = makeCacheFileFromObject(c, pathComps, obj)
  112. if err != nil {
  113. // TODO 日志记录
  114. logger.Tracef("make cache file from object: %v", err)
  115. return nil
  116. }
  117. return ch
  118. }
  119. // 创建一个缓存目录。如果目录已经存在,则会重置目录属性。如果加载过程中发生了错误,或者目标位置是一个文件,则会返回nil
  120. func (c *Cache) CreateDir(pathComps []string) *CacheDir {
  121. ch, err := createNewCacheDir(c, pathComps)
  122. if err != nil {
  123. // TODO 日志记录
  124. return nil
  125. }
  126. return ch
  127. }
  128. type CreateDirOption struct {
  129. ModTime time.Time
  130. }
  131. // 加载指定缓存目录,如果目录不存在,则使用createOpt选项创建目录,而如果createOpt为nil,那么会返回nil。
  132. func (c *Cache) LoadDir(pathComps []string, createOpt *CreateDirOption) *CacheDir {
  133. ch, err := loadCacheDir(c, pathComps)
  134. if err == nil {
  135. return ch
  136. }
  137. if !os.IsNotExist(err) {
  138. // TODO 日志记录
  139. return nil
  140. }
  141. if createOpt == nil {
  142. return nil
  143. }
  144. // 创建目录
  145. ch, err = makeCacheDirFromOption(c, pathComps, *createOpt)
  146. if err != nil {
  147. // TODO 日志记录
  148. return nil
  149. }
  150. return ch
  151. }
  152. // 加载指定路径下的所有缓存条目信息
  153. func (c *Cache) StatMany(pathComps []string) []CacheEntryInfo {
  154. osEns, err := os.ReadDir(c.GetCacheMetaPath(pathComps...))
  155. if err != nil {
  156. return nil
  157. }
  158. var infos []CacheEntryInfo
  159. for _, e := range osEns {
  160. if e.IsDir() {
  161. info, err := loadCacheDirInfo(c, append(lo2.ArrayClone(pathComps), e.Name()))
  162. if err != nil {
  163. continue
  164. }
  165. infos = append(infos, *info)
  166. } else {
  167. info, err := loadCacheFileInfo(c, append(lo2.ArrayClone(pathComps), e.Name()))
  168. if err != nil {
  169. continue
  170. }
  171. infos = append(infos, *info)
  172. }
  173. }
  174. return infos
  175. }
  176. // 删除指定路径的缓存文件或目录。删除目录时如果目录不为空,则会报错。
  177. func (c *Cache) Remove(pathComps []string) error {
  178. return fmt.Errorf("not implemented")
  179. }
  180. // 移动指定路径的缓存文件或目录到新的路径。如果目标路径已经存在,则会报错。
  181. //
  182. // 如果移动成功,则返回移动后的缓存文件或目录。如果文件或目录不存在,则返回nil。
  183. func (c *Cache) Move(pathComps []string, newPathComps []string) (CacheEntry, error) {
  184. return nil, fmt.Errorf("not implemented")
  185. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。