Skip to content

Commit 3a6e07a

Browse files
committed
memory: add --memory-discard flag for speed testing - fixes rclone#9037
1 parent c36f99d commit 3a6e07a

File tree

1 file changed

+44
-7
lines changed

1 file changed

+44
-7
lines changed

backend/memory/memory.go

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"context"
77
"crypto/md5"
88
"encoding/hex"
9+
"errors"
910
"fmt"
1011
"io"
1112
"path"
@@ -24,7 +25,8 @@ import (
2425
var (
2526
hashType = hash.MD5
2627
// the object storage is persistent
27-
buckets = newBucketsInfo()
28+
buckets = newBucketsInfo()
29+
errWriteOnly = errors.New("can't read when using --memory-discard")
2830
)
2931

3032
// Register with Fs
@@ -33,12 +35,32 @@ func init() {
3335
Name: "memory",
3436
Description: "In memory object storage system.",
3537
NewFs: NewFs,
36-
Options: []fs.Option{},
38+
Options: []fs.Option{{
39+
Name: "discard",
40+
Default: false,
41+
Advanced: true,
42+
Help: `If set all writes will be discarded and reads will return an error
43+
44+
If set then when files are uploaded the contents not be saved. The
45+
files will appear to have been uploaded but will give an error on
46+
read. Files will have their MD5 sum calculated on upload which takes
47+
very little CPU time and allows the transfers to be checked.
48+
49+
This can be useful for testing performance.
50+
51+
Probably most easily used by using the connection string syntax:
52+
53+
:memory,discard:bucket
54+
55+
`,
56+
}},
3757
})
3858
}
3959

4060
// Options defines the configuration for this backend
41-
type Options struct{}
61+
type Options struct {
62+
Discard bool `config:"discard"`
63+
}
4264

4365
// Fs represents a remote memory server
4466
type Fs struct {
@@ -164,6 +186,7 @@ type objectData struct {
164186
hash string
165187
mimeType string
166188
data []byte
189+
size int64
167190
}
168191

169192
// Object describes a memory object
@@ -558,7 +581,7 @@ func (o *Object) Hash(ctx context.Context, t hash.Type) (string, error) {
558581
if t != hashType {
559582
return "", hash.ErrUnsupported
560583
}
561-
if o.od.hash == "" {
584+
if o.od.hash == "" && !o.fs.opt.Discard {
562585
sum := md5.Sum(o.od.data)
563586
o.od.hash = hex.EncodeToString(sum[:])
564587
}
@@ -567,7 +590,7 @@ func (o *Object) Hash(ctx context.Context, t hash.Type) (string, error) {
567590

568591
// Size returns the size of an object in bytes
569592
func (o *Object) Size() int64 {
570-
return int64(len(o.od.data))
593+
return o.od.size
571594
}
572595

573596
// ModTime returns the modification time of the object
@@ -593,6 +616,9 @@ func (o *Object) Storable() bool {
593616

594617
// Open an object for read
595618
func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.ReadCloser, err error) {
619+
if o.fs.opt.Discard {
620+
return nil, errWriteOnly
621+
}
596622
var offset, limit int64 = 0, -1
597623
for _, option := range options {
598624
switch x := option.(type) {
@@ -624,13 +650,24 @@ func (o *Object) Open(ctx context.Context, options ...fs.OpenOption) (in io.Read
624650
// The new object may have been created if an error is returned
625651
func (o *Object) Update(ctx context.Context, in io.Reader, src fs.ObjectInfo, options ...fs.OpenOption) (err error) {
626652
bucket, bucketPath := o.split()
627-
data, err := io.ReadAll(in)
653+
var data []byte
654+
var size int64
655+
var hash string
656+
if o.fs.opt.Discard {
657+
h := md5.New()
658+
size, err = io.Copy(h, in)
659+
hash = hex.EncodeToString(h.Sum(nil))
660+
} else {
661+
data, err = io.ReadAll(in)
662+
size = int64(len(data))
663+
}
628664
if err != nil {
629665
return fmt.Errorf("failed to update memory object: %w", err)
630666
}
631667
o.od = &objectData{
632668
data: data,
633-
hash: "",
669+
size: size,
670+
hash: hash,
634671
modTime: src.ModTime(ctx),
635672
mimeType: fs.MimeType(ctx, src),
636673
}

0 commit comments

Comments
 (0)