Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alist-org
GitHub Repository: alist-org/alist
Path: blob/main/drivers/mega/util.go
1987 views
1
package mega
2
3
import (
4
"context"
5
"fmt"
6
"github.com/alist-org/alist/v3/pkg/utils"
7
"github.com/t3rm1n4l/go-mega"
8
"io"
9
"sync"
10
"time"
11
)
12
13
// do others that not defined in Driver interface
14
// openObject represents a download in progress
15
type openObject struct {
16
ctx context.Context
17
mu sync.Mutex
18
d *mega.Download
19
id int
20
skip int64
21
chunk []byte
22
closed bool
23
}
24
25
// get the next chunk
26
func (oo *openObject) getChunk(ctx context.Context) (err error) {
27
if oo.id >= oo.d.Chunks() {
28
return io.EOF
29
}
30
var chunk []byte
31
err = utils.Retry(3, time.Second, func() (err error) {
32
chunk, err = oo.d.DownloadChunk(oo.id)
33
return err
34
})
35
if err != nil {
36
return err
37
}
38
oo.id++
39
oo.chunk = chunk
40
return nil
41
}
42
43
// Read reads up to len(p) bytes into p.
44
func (oo *openObject) Read(p []byte) (n int, err error) {
45
oo.mu.Lock()
46
defer oo.mu.Unlock()
47
if oo.closed {
48
return 0, fmt.Errorf("read on closed file")
49
}
50
// Skip data at the start if requested
51
for oo.skip > 0 {
52
_, size, err := oo.d.ChunkLocation(oo.id)
53
if err != nil {
54
return 0, err
55
}
56
if oo.skip < int64(size) {
57
break
58
}
59
oo.id++
60
oo.skip -= int64(size)
61
}
62
if len(oo.chunk) == 0 {
63
err = oo.getChunk(oo.ctx)
64
if err != nil {
65
return 0, err
66
}
67
if oo.skip > 0 {
68
oo.chunk = oo.chunk[oo.skip:]
69
oo.skip = 0
70
}
71
}
72
n = copy(p, oo.chunk)
73
oo.chunk = oo.chunk[n:]
74
return n, nil
75
}
76
77
// Close closed the file - MAC errors are reported here
78
func (oo *openObject) Close() (err error) {
79
oo.mu.Lock()
80
defer oo.mu.Unlock()
81
if oo.closed {
82
return nil
83
}
84
err = utils.Retry(3, 500*time.Millisecond, func() (err error) {
85
return oo.d.Finish()
86
})
87
if err != nil {
88
return fmt.Errorf("failed to finish download: %w", err)
89
}
90
oo.closed = true
91
return nil
92
}
93
94