|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- package vfs
-
- import (
- "context"
- "os"
- "time"
-
- cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
- "gitlink.org.cn/cloudream/storage/client2/internal/mount/fuse"
- "gitlink.org.cn/cloudream/storage/client2/internal/mount/vfs/cache"
- "gitlink.org.cn/cloudream/storage/common/pkgs/db2"
- "gorm.io/gorm"
- )
-
- type Root struct {
- vfs *Vfs
- }
-
- func newRoot(vfs *Vfs) *Root {
- return &Root{
- vfs: vfs,
- }
- }
-
- func (r *Root) PathComps() []string {
- return []string{}
- }
-
- func (r *Root) Name() string {
- return ""
- }
-
- func (r *Root) Size() int64 {
- return 0
- }
-
- func (r *Root) Mode() os.FileMode {
- return os.ModeDir | 0755
- }
-
- func (r *Root) ModTime() time.Time {
- return time.Now()
- }
-
- func (r *Root) IsDir() bool {
- return true
- }
-
- func (r *Root) SetModTime(time time.Time) error {
- return nil
- }
-
- // 如果不存在,应该返回ErrNotExists
- func (r *Root) Child(ctx context.Context, name string) (fuse.FsEntry, error) {
- ca := r.vfs.cache.Stat([]string{name})
-
- if ca == nil {
- bkt, err := r.vfs.db.Bucket().GetByName(r.vfs.db.DefCtx(), name)
- if err == nil {
- dir := r.vfs.cache.LoadDir([]string{name}, &cache.CreateDirOption{
- ModTime: bkt.CreateTime,
- })
- if dir == nil {
- return nil, fuse.ErrNotExists
- }
-
- return newBucketFromCache(dir.Info(), r.vfs), nil
- }
-
- if err == gorm.ErrRecordNotFound {
- return nil, fuse.ErrNotExists
- }
-
- return nil, err
- }
-
- if ca.IsDir {
- return newBucketFromCache(*ca, r.vfs), nil
- }
-
- return newFileFromCache(*ca, r.vfs), nil
- }
-
- func (r *Root) Children(ctx context.Context) ([]fuse.FsEntry, error) {
- return r.listChildren()
- }
-
- func (r *Root) ReadChildren() (fuse.DirReader, error) {
- ens, err := r.listChildren()
- if err != nil {
- return nil, err
- }
-
- return newFuseDirReader(ens), nil
- }
-
- func (r *Root) listChildren() ([]fuse.FsEntry, error) {
- var ens []fuse.FsEntry
-
- infos := r.vfs.cache.StatMany([]string{})
-
- bkts, err := r.vfs.db.Bucket().GetAll(r.vfs.db.DefCtx())
- if err != nil {
- return nil, err
- }
-
- bktMap := make(map[string]*cdssdk.Bucket)
- for _, bkt := range bkts {
- b := bkt
- bktMap[bkt.Name] = &b
- }
-
- for _, c := range infos {
- delete(bktMap, c.PathComps[len(c.PathComps)-1])
-
- if c.IsDir {
- ens = append(ens, newBucketFromCache(c, r.vfs))
- } else {
- ens = append(ens, newFileFromCache(c, r.vfs))
- }
- }
-
- // 将远端目录同步到本地缓存中,防止在给目录中的远端对象创建本地缓存时,顺便创建的目录的元数据不对的情况
- for _, bkt := range bktMap {
- dir := r.vfs.cache.LoadDir([]string{bkt.Name}, &cache.CreateDirOption{
- ModTime: bkt.CreateTime,
- })
-
- if dir == nil {
- continue
- }
-
- ens = append(ens, newBucketFromCache(dir.Info(), r.vfs))
- }
-
- return ens, nil
- }
-
- func (r *Root) NewDir(ctx context.Context, name string) (fuse.FsDir, error) {
- cache := r.vfs.cache.CreateDir([]string{name})
- if cache == nil {
- return nil, fuse.ErrPermission
- }
-
- // TODO 用户ID,失败了可以打个日志
- // TODO 生成系统事件
- // 不关注创建是否成功,仅尝试一下
- r.vfs.db.Bucket().Create(r.vfs.db.DefCtx(), 1, name, cache.ModTime())
-
- return newBucketFromCache(cache.Info(), r.vfs), nil
- }
-
- func (r *Root) NewFile(ctx context.Context, name string, flags uint32) (fuse.FileHandle, error) {
- cache := r.vfs.cache.CreateFile([]string{name})
- if cache == nil {
- return nil, fuse.ErrPermission
- }
- // Open之后会给cache的引用计数额外+1,即使cache先于FileHandle被关闭,
- // 也有有FileHandle的计数保持cache的有效性
-
- fileNode := newFileFromCache(cache.Info(), r.vfs)
-
- if flags&uint32(os.O_WRONLY) != 0 {
- hd := cache.Open(false)
- return newFileHandle(fileNode, hd), nil
- }
-
- if flags&uint32(os.O_RDONLY) != 0 {
- hd := cache.Open(true)
- return newFileHandle(fileNode, hd), nil
- }
-
- return nil, fuse.ErrPermission
- }
-
- func (r *Root) RemoveChild(ctx context.Context, name string) error {
- err := r.vfs.cache.Remove([]string{name})
- if err != nil {
- return err
- }
-
- // TODO 生成系统事件
- // 不关心是否成功
- r.vfs.db.DoTx(func(tx db2.SQLContext) error {
- d := r.vfs.db
-
- bkt, err := d.Bucket().GetByName(tx, name)
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- return nil
- }
- }
-
- return d.Bucket().DeleteComplete(tx, bkt.BucketID)
- })
-
- return nil
- }
-
- func (r *Root) MoveChild(ctx context.Context, oldName string, newName string, newParent fuse.FsDir) error {
-
- // TODO 有问题
-
- newParentNode := newParent.(FuseNode)
- _, err := r.vfs.cache.Move([]string{oldName}, append(newParentNode.PathComps(), newName))
- if err != nil {
- return err
- }
-
- d := r.vfs.db
- // 如果目标节点是根节点,那么就是重命名桶
- if _, ok := newParent.(*Root); ok {
- d.DoTx(func(tx db2.SQLContext) error {
- _, err := d.Bucket().GetByName(tx, newName)
- if err == nil {
- // 目标节点已经存在,不能重命名,直接退出
- return err
- }
-
- oldBkt, err := d.Bucket().GetByName(tx, oldName)
- if err != nil {
- // 源节点不存在,直接退出
- return err
- }
-
- // 不关注重命名是否成功,仅尝试一下
- return d.Bucket().Rename(tx, oldBkt.BucketID, newName)
- })
- } else {
- // TODO 做法存疑
- // 其他情况则删除旧桶
- d.DoTx(func(tx db2.SQLContext) error {
- oldBkt, err := d.Bucket().GetByName(tx, oldName)
- if err != nil {
- // 源节点不存在,直接退出
- return err
- }
-
- return d.Bucket().DeleteComplete(tx, oldBkt.BucketID)
- })
- }
-
- return nil
- }
-
- var _ fuse.FsDir = (*Root)(nil)
- var _ FuseNode = (*Root)(nil)
|