-
Notifications
You must be signed in to change notification settings - Fork 0
/
idle.go
127 lines (101 loc) · 2.33 KB
/
idle.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package smartremote
import (
"errors"
)
func (f *File) wantsFollowing(offset int64) int {
block := offset / f.blkSize
if block*f.blkSize != offset {
// wrong offset (not block aligned), don't care
return 0
}
if f.status.Contains(uint32(block)) {
return 0
}
return int(f.blkSize)
}
func (f *File) getBlockCount() int64 {
// computer number of blocks
blkCount := f.size / f.blkSize
if f.size%f.blkSize != 0 {
blkCount += 1
}
return blkCount
}
func (f *File) isComplete() bool {
if f.complete {
return true
}
if f.status.IsEmpty() {
return false
}
if int64(f.status.GetCardinality()) != f.getBlockCount() {
return false
}
f.dlm.logf("file is now complete, marking as such")
f.complete = true
f.savePart()
return true
}
func (f *File) firstMissing() int64 {
if f.isComplete() {
return -1
}
err := f.getSize()
if err != nil {
f.dlm.logf("failed to get file size: %s", err)
return -1 // can't be helped
}
// get number of blocks
blkCount := f.getBlockCount()
// find out first missing block
// TODO this can probably be optimized, roaring api may have something
for i := int64(0); i < blkCount; i++ {
if !f.status.Contains(uint32(i)) {
return i * f.blkSize
}
}
// ?????
// did we have more blocks in status than we need? did file size change? this sounds like everything is likely corrupted...
return -1
}
func (f *File) ingestData(b []byte, offset int64) error {
if !f.hasSize {
return errors.New("invalid operation, file size unknown")
}
block := offset / f.blkSize
if offset%f.blkSize != 0 {
return errors.New("invalid offset (not block aligned)")
}
blkCount := f.size / f.blkSize
if f.size%f.blkSize != 0 {
blkCount += 1
}
if block >= blkCount {
return errors.New("invalid offset (over EOF)")
}
if block == blkCount-1 {
// last block
lastBlockSize := f.size % f.blkSize
if lastBlockSize == 0 {
lastBlockSize = f.blkSize
}
if int64(len(b)) != lastBlockSize {
return errors.New("invalid buffer length (invalid final block size)")
}
} else {
if int64(len(b)) != f.blkSize {
return errors.New("invalid buffer length (not block size)")
}
}
_, err := f.local.WriteAt(b, offset)
if err != nil {
return err
}
// mark blocks as received
f.status.Add(uint32(block))
f.savePart()
return nil
}
func (f *File) getBlockSize() int64 {
return f.blkSize
}