-
Notifications
You must be signed in to change notification settings - Fork 1
/
backend.go
105 lines (91 loc) · 2.21 KB
/
backend.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
package s3mem
import (
"io"
"strconv"
"time"
"github.com/yottachain/YTS3/yts3"
)
var (
emptyPrefix = &yts3.Prefix{}
)
type Backend struct {
timeSource yts3.TimeSource
versionGenerator *versionGenerator
versionSeed int64
versionSeedSet bool
versionScratch []byte
}
var _ yts3.Backend = &Backend{}
var _ yts3.VersionedBackend = &Backend{}
type Option func(b *Backend)
func WithTimeSource(timeSource yts3.TimeSource) Option {
return func(b *Backend) { b.timeSource = timeSource }
}
func WithVersionSeed(seed int64) Option {
return func(b *Backend) { b.versionSeed = seed; b.versionSeedSet = true }
}
func New(opts ...Option) *Backend {
b := &Backend{}
for _, opt := range opts {
opt(b)
}
if b.timeSource == nil {
b.timeSource = yts3.DefaultTimeSource()
}
if b.versionGenerator == nil {
if b.versionSeedSet {
b.versionGenerator = newVersionGenerator(uint64(b.versionSeed), 0)
} else {
b.versionGenerator = newVersionGenerator(uint64(b.timeSource.Now().UnixNano()), 0)
}
}
return b
}
func getContentByMeta(meta map[string]string) *yts3.Content {
var content yts3.Content
content.ETag = meta["ETag"]
if contentLengthString, ok := meta["content-length"]; ok {
size, err := strconv.ParseInt(contentLengthString, 10, 64)
if err == nil {
content.Size = size
}
}
if contentLengthString, ok := meta["contentLength"]; ok {
size, err := strconv.ParseInt(contentLengthString, 10, 64)
if err == nil {
content.Size = size
}
}
if lastModifyString, ok := meta["x-amz-meta-s3b-last-modified"]; ok {
lastModifyTime, err := time.ParseInLocation("20060102T150405Z", lastModifyString, time.Local)
if err == nil {
content.LastModified = yts3.ContentTime{lastModifyTime}
}
}
return &content
}
func (db *Backend) nextVersion() yts3.VersionID {
v, scr := db.versionGenerator.Next(db.versionScratch)
db.versionScratch = scr
return v
}
type ContentReader struct {
io.ReadCloser
}
func (cr *ContentReader) Close() error {
return cr.ReadCloser.Close()
}
func (cr *ContentReader) Read(buf []byte) (int, error) {
var nc int
var err2 error
for i := 0; i < 5; i++ {
n, err := cr.ReadCloser.Read(buf)
if err == nil {
nc = n
break
} else {
err2 = err
}
}
return nc, err2
}