|
- package rclone
-
- import (
- "context"
- "crypto/sha256"
- "io"
- "time"
-
- "github.com/inhies/go-bytesize"
- "github.com/rclone/rclone/fs"
- "gitlink.org.cn/cloudream/common/pkgs/logger"
- "gitlink.org.cn/cloudream/common/utils/io2"
- stgtypes "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
- jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types"
- )
-
- type BaseStore struct {
- Fs fs.Fs
- Detail *jcstypes.UserSpaceDetail
- }
-
- func NewBaseStore(fs fs.Fs, detail *jcstypes.UserSpaceDetail) *BaseStore {
- return &BaseStore{
- Fs: fs,
- Detail: detail,
- }
- }
-
- func (s *BaseStore) Write(pat jcstypes.JPath, stream io.Reader, opt stgtypes.WriteOption) (stgtypes.FileInfo, error) {
- modTime := opt.ModTime
- if modTime.IsZero() {
- modTime = time.Now()
- }
-
- dir := pat.CopyParent()
- if dir.Len() > 0 {
- err := s.Fs.Mkdir(context.Background(), dir.String())
- if err != nil {
- return stgtypes.FileInfo{}, err
- }
- }
-
- counter := io2.Counter(stream)
- hasher := io2.NewReadHasher(sha256.New(), counter)
-
- _, err := s.Fs.Put(context.Background(), hasher, &ObjectInfo{
- RemoteValue: pat.String(),
- ModTimeValue: modTime,
- SizeValue: -1,
- })
- if err != nil {
- return stgtypes.FileInfo{}, err
- }
-
- return stgtypes.FileInfo{
- Path: pat,
- Size: counter.Count(),
- Hash: jcstypes.NewFullHash(hasher.Sum()),
- }, nil
- }
-
- func (s *BaseStore) Read(objPath jcstypes.JPath, opt stgtypes.OpenOption) (io.ReadCloser, error) {
- if opt.Length == 0 {
- return io2.ErrorReader(io.EOF), nil
- }
-
- var opts []fs.OpenOption
- if opt.Length > 0 {
- opts = append(opts, &fs.RangeOption{
- Start: opt.Offset,
- End: opt.Offset + opt.Length - 1,
- })
- } else if opt.Offset > 0 {
- opts = append(opts, &fs.SeekOption{
- Offset: opt.Offset,
- })
- }
-
- obj, err := s.Fs.NewObject(context.Background(), objPath.String())
- if err != nil {
- return nil, err
- }
-
- return obj.Open(context.Background(), opts...)
- }
-
- func (s *BaseStore) Mkdir(path jcstypes.JPath) error {
- return s.Fs.Mkdir(context.Background(), path.String())
- }
-
- func (s *BaseStore) ReadDir(pat jcstypes.JPath) stgtypes.DirReader {
- return NewDirReader(s.Fs, pat.String(), pat.Clone())
- }
-
- func (s *BaseStore) CleanTemps() {
- log := s.getLogger()
-
- startTime := time.Now()
- tempDir := Join(s.Detail.UserSpace.WorkingDir.String(), stgtypes.TempWorkingDir)
- cnt, size := s.cleanTemps(tempDir, false)
-
- log.Infof("clean %d temp files, size: %v, time: %v", cnt, bytesize.ByteSize(size), time.Since(startTime))
- }
-
- func (s *BaseStore) cleanTemps(root string, removeRoot bool) (int, int64) {
- log := s.getLogger()
-
- es, err := s.Fs.List(context.Background(), root)
- if err != nil {
- log.Warnf("list dir %v: %v", root, err)
- return 0, 0
- }
-
- cnt := 0
- size := int64(0)
- for _, e := range es {
- switch e := e.(type) {
- case fs.Object:
- err := e.Remove(context.Background())
- if err != nil {
- log.Warnf("remove file %v: %v", e.Remote(), err)
- } else {
- cnt++
- size += e.Size()
- }
-
- case fs.Directory:
- c, s := s.cleanTemps(e.Remote(), true)
- cnt += c
- size += s
- }
- }
-
- if removeRoot {
- err := s.Fs.Rmdir(context.Background(), root)
- if err != nil {
- log.Warnf("remove dir %v: %v", root, err)
- }
- }
-
- return cnt, size
- }
-
- func (s *BaseStore) Test() error {
- _, err := s.Fs.List(context.Background(), "")
- return err
- }
-
- func (s *BaseStore) getLogger() logger.Logger {
- return logger.WithField("BaseStore", "RClone").WithField("UserSpace", s.Detail.UserSpace)
- }
|