Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ETags #625

Merged
merged 45 commits into from
Oct 3, 2023
Merged

ETags #625

Show file tree
Hide file tree
Changes from 36 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
bd15bfd
worker,bus: add ObjectMetadata
peterjan Sep 21, 2023
f9bd141
stores: add MimeType to object
peterjan Sep 22, 2023
3096b84
stores: add CreateMultipartOptions
peterjan Sep 24, 2023
b471ac7
bus,worker: fix CompleteMultipartUpload, CreateMultipartUpload signature
peterjan Sep 25, 2023
0a9428e
worker: cleanup PR
peterjan Sep 25, 2023
795b36f
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 25, 2023
efac727
bus: fix MultipartAddPartRequest
peterjan Sep 25, 2023
1f43282
testing: fix TestUploadDownloadExtended,TestObjectEntries
peterjan Sep 25, 2023
7a4461e
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 25, 2023
669e76f
testing: fix TestObjectEntries
peterjan Sep 25, 2023
4f59a5e
testing: avoid NDF in TestSlabBufferStats
peterjan Sep 25, 2023
ed28864
bus: add ContentType method
peterjan Sep 25, 2023
6f1a8b2
api: add CopyObjectOptions
peterjan Sep 25, 2023
6b58856
worker,bus: add etag
peterjan Sep 25, 2023
7c72be1
testing: fix TestSQLMetadataStore
peterjan Sep 25, 2023
821a212
wip: tmp commit
peterjan Sep 25, 2023
484f2fe
testing: fix TestCopyObject
peterjan Sep 25, 2023
d2d8b6b
testing: fix TestObjectEntries
peterjan Sep 26, 2023
57c2846
modules: update gofakes3
peterjan Sep 26, 2023
70e4ad0
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 27, 2023
1b13773
stores: update migration label
peterjan Sep 27, 2023
e595555
fix lint
peterjan Sep 27, 2023
074aa64
testing,migrations: fix TestObjectEntries + avoid conflict
peterjan Sep 27, 2023
95ef7ea
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 27, 2023
dc59b40
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 27, 2023
769f42b
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 27, 2023
2cc2a59
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 27, 2023
fa53b11
worker: fix multiple write
peterjan Sep 27, 2023
67180da
Merge branch 'pj/mime-type' into pj/serve-content
peterjan Sep 28, 2023
09967ac
Merge branch 'pj/etags' into pj/serve-content
peterjan Sep 28, 2023
9e30adc
worker: add serveContent
peterjan Sep 28, 2023
d3dc995
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 28, 2023
2335248
fix: lint
peterjan Sep 28, 2023
67fa235
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 28, 2023
a9cc9ea
fix: TestMultipartUploadWithUploadPackingRegression
peterjan Sep 28, 2023
01827c5
bus: move ContentType method
peterjan Sep 28, 2023
2a3a3a2
worker: set etag on response header on upload
peterjan Sep 28, 2023
c9d897e
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Sep 29, 2023
423a41a
worker: implement MR remarks
peterjan Oct 2, 2023
bbe8054
api: add UploadObjectResponse,UploadMultipartUploadPartResponse
peterjan Oct 2, 2023
758da29
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Oct 2, 2023
12e06a4
worker: allow seek at offset
peterjan Oct 2, 2023
3059531
Merge branch 'master' of https://github.com/SiaFoundation/renterd int…
peterjan Oct 3, 2023
c65708d
Merge branch 'master' into pj/serve-content
ChrisSchinnerl Oct 3, 2023
3b15871
worker: etag -> eTag
ChrisSchinnerl Oct 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions api/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ type Object struct {

// ObjectMetadata contains various metadata about an object.
type ObjectMetadata struct {
ETag string `json:"eTag"`
Health float64 `json:"health"`
MimeType string `json:"mimeType"`
ModTime time.Time `json:"modTime"`
Expand All @@ -222,14 +223,14 @@ type ObjectMetadata struct {

// LastModified returns the object's ModTime formatted for use in the
// 'Last-Modified' header
func (o *Object) LastModified() string {
func (o ObjectMetadata) LastModified() string {
return o.ModTime.UTC().Format(http.TimeFormat)
}

// ContentType returns the object's MimeType for use in the 'Content-Type'
// header, if the object's mime type is empty we try and deduce it from the
// extension in the object's name.
func (o Object) ContentType() string {
func (o ObjectMetadata) ContentType() string {
if o.MimeType != "" {
return o.MimeType
}
Expand All @@ -248,6 +249,7 @@ type ObjectAddRequest struct {
Object object.Object `json:"object"`
UsedContracts map[types.PublicKey]types.FileContractID `json:"usedContracts"`
MimeType string `json:"mimeType"`
ETag string `json:"eTag"`
}

// ObjectsResponse is the response type for the /objects endpoint.
Expand Down Expand Up @@ -573,7 +575,7 @@ type (
}
MultipartAddPartRequest struct {
Bucket string `json:"bucket"`
Etag string `json:"eTag"`
ETag string `json:"eTag"`
Path string `json:"path"`
ContractSet string `json:"contractSet"`
UploadID string `json:"uploadID"`
Expand Down Expand Up @@ -712,6 +714,6 @@ type AddPartialSlabResponse struct {
Slabs []object.PartialSlab `json:"slabs"`
}

func FormatEtag(etag string) string {
return fmt.Sprintf("\"%s\"", etag)
func FormatETag(ETag string) string {
return fmt.Sprintf("\"%s\"", ETag)
}
13 changes: 8 additions & 5 deletions bus/bus.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,14 +117,14 @@ type (
ObjectsBySlabKey(ctx context.Context, bucket string, slabKey object.EncryptionKey) ([]api.ObjectMetadata, error)
SearchObjects(ctx context.Context, bucket, substring string, offset, limit int) ([]api.ObjectMetadata, error)
CopyObject(ctx context.Context, srcBucket, dstBucket, srcPath, dstPath, mimeType string) (api.ObjectMetadata, error)
UpdateObject(ctx context.Context, bucket, path, contractSet string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID, mimeType string) error
UpdateObject(ctx context.Context, bucket, path, contractSet, ETag, mimeType string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID) error
RemoveObject(ctx context.Context, bucket, path string) error
RemoveObjects(ctx context.Context, bucket, prefix string) error
RenameObject(ctx context.Context, bucket, from, to string) error
RenameObjects(ctx context.Context, bucket, from, to string) error

AbortMultipartUpload(ctx context.Context, bucket, path string, uploadID string) (err error)
AddMultipartPart(ctx context.Context, bucket, path, contractSet, uploadID string, partNumber int, slices []object.SlabSlice, partialSlab []object.PartialSlab, eTag string, usedContracts map[types.PublicKey]types.FileContractID) (err error)
AddMultipartPart(ctx context.Context, bucket, path, contractSet, eTag, uploadID string, partNumber int, slices []object.SlabSlice, partialSlab []object.PartialSlab, usedContracts map[types.PublicKey]types.FileContractID) (err error)
CompleteMultipartUpload(ctx context.Context, bucket, path, uploadID string, parts []api.MultipartCompletedPart) (_ api.MultipartCompleteResponse, err error)
CreateMultipartUpload(ctx context.Context, bucket, path string, ec object.EncryptionKey, mimeType string) (api.MultipartCreateResponse, error)
MultipartUpload(ctx context.Context, uploadID string) (resp api.MultipartUpload, _ error)
Expand Down Expand Up @@ -1026,7 +1026,7 @@ func (b *bus) objectsHandlerPUT(jc jape.Context) {
} else if aor.Bucket == "" {
aor.Bucket = api.DefaultBucketName
}
jc.Check("couldn't store object", b.ms.UpdateObject(jc.Request.Context(), aor.Bucket, jc.PathParam("path"), aor.ContractSet, aor.Object, aor.UsedContracts, aor.MimeType))
jc.Check("couldn't store object", b.ms.UpdateObject(jc.Request.Context(), aor.Bucket, jc.PathParam("path"), aor.ContractSet, aor.ETag, aor.MimeType, aor.Object, aor.UsedContracts))
}

func (b *bus) objectsCopyHandlerPOST(jc jape.Context) {
Expand All @@ -1039,6 +1039,9 @@ func (b *bus) objectsCopyHandlerPOST(jc jape.Context) {
if jc.Check("couldn't copy object", err) != nil {
return
}

jc.ResponseWriter.Header().Set("Last-Modified", om.LastModified())
jc.ResponseWriter.Header().Set("ETag", api.FormatETag(om.ETag))
jc.Encode(om)
}

Expand Down Expand Up @@ -1897,7 +1900,7 @@ func (b *bus) multipartHandlerUploadPartPUT(jc jape.Context) {
} else if req.ContractSet == "" {
jc.Error(errors.New("contract_set must be non-empty"), http.StatusBadRequest)
return
} else if req.Etag == "" {
} else if req.ETag == "" {
ChrisSchinnerl marked this conversation as resolved.
Show resolved Hide resolved
jc.Error(errors.New("etag must be non-empty"), http.StatusBadRequest)
return
} else if req.PartNumber <= 0 || req.PartNumber > gofakes3.MaxUploadPartNumber {
Expand All @@ -1907,7 +1910,7 @@ func (b *bus) multipartHandlerUploadPartPUT(jc jape.Context) {
jc.Error(errors.New("upload_id must be non-empty"), http.StatusBadRequest)
return
}
err := b.ms.AddMultipartPart(jc.Request.Context(), req.Bucket, req.Path, req.ContractSet, req.UploadID, req.PartNumber, req.Slices, req.PartialSlabs, req.Etag, req.UsedContracts)
err := b.ms.AddMultipartPart(jc.Request.Context(), req.Bucket, req.Path, req.ContractSet, req.ETag, req.UploadID, req.PartNumber, req.Slices, req.PartialSlabs, req.UsedContracts)
if jc.Check("failed to upload part", err) != nil {
return
}
Expand Down
7 changes: 4 additions & 3 deletions bus/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -671,14 +671,15 @@ func (c *Client) Object(ctx context.Context, path string, opts ...api.ObjectsOpt
}

// AddObject stores the provided object under the given path.
func (c *Client) AddObject(ctx context.Context, bucket, path, contractSet string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID, mimeType string) (err error) {
func (c *Client) AddObject(ctx context.Context, bucket, path, contractSet, eTag, mimeType string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID) (err error) {
path = strings.TrimPrefix(path, "/")
err = c.c.WithContext(ctx).PUT(fmt.Sprintf("/objects/%s", path), api.ObjectAddRequest{
Bucket: bucket,
ContractSet: contractSet,
Object: o,
UsedContracts: usedContracts,
MimeType: mimeType,
ETag: eTag,
})
return
}
Expand Down Expand Up @@ -975,10 +976,10 @@ func (c *Client) CreateMultipartUpload(ctx context.Context, bucket, path string,
return
}

func (c *Client) AddMultipartPart(ctx context.Context, bucket, path, contractSet, uploadID string, partNumber int, slices []object.SlabSlice, partialSlab []object.PartialSlab, etag string, usedContracts map[types.PublicKey]types.FileContractID) (err error) {
func (c *Client) AddMultipartPart(ctx context.Context, bucket, path, contractSet, eTag, uploadID string, partNumber int, slices []object.SlabSlice, partialSlab []object.PartialSlab, usedContracts map[types.PublicKey]types.FileContractID) (err error) {
err = c.c.WithContext(ctx).PUT("/multipart/part", api.MultipartAddPartRequest{
Bucket: bucket,
Etag: etag,
ETag: eTag,
Path: path,
ContractSet: contractSet,
UploadID: uploadID,
Expand Down
26 changes: 15 additions & 11 deletions internal/testing/cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ import (
"lukechampine.com/frand"
)

const (
testEtag = "d34db33f"
testMimeType = "application/octet-stream"
)

// TestNewTestCluster is a test for creating a cluster of Nodes for testing,
// making sure that it forms contracts, renews contracts and shuts down.
func TestNewTestCluster(t *testing.T) {
Expand Down Expand Up @@ -60,7 +65,7 @@ func TestNewTestCluster(t *testing.T) {
}

// Try talking to the bus API by adding an object.
err = b.AddObject(context.Background(), api.DefaultBucketName, "foo", testAutopilotConfig.Contracts.Set, object.Object{
err = b.AddObject(context.Background(), api.DefaultBucketName, "foo", testAutopilotConfig.Contracts.Set, testEtag, testMimeType, object.Object{
Key: object.GenerateEncryptionKey(),
Slabs: []object.SlabSlice{
{
Expand All @@ -73,7 +78,7 @@ func TestNewTestCluster(t *testing.T) {
Length: 0,
},
},
}, map[types.PublicKey]types.FileContractID{}, "application/octet-stream")
}, map[types.PublicKey]types.FileContractID{})
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -300,7 +305,8 @@ func TestObjectEntries(t *testing.T) {
t.SkipNow()
}

// assert mod time & mime type and clear it afterwards so we can compare
// assertMetadata asserts ModTime, ETag and MimeType are set and then clears
// them afterwards so we can compare without having to specify the metadata
start := time.Now()
assertMetadata := func(entries []api.ObjectMetadata) {
for i := range entries {
Expand All @@ -315,6 +321,12 @@ func TestObjectEntries(t *testing.T) {
t.Fatal("mime type should be set", entries[i].MimeType, entries[i].Name)
}
entries[i].MimeType = ""

// assert etag
if entries[i].ETag == "" {
t.Fatal("ETag should be set")
}
entries[i].ETag = ""
}
}

Expand Down Expand Up @@ -398,8 +410,6 @@ func TestObjectEntries(t *testing.T) {
if err != nil {
t.Fatal(err, test.path)
}

// assert mod time & mime type and clear it afterwards so we can compare
assertMetadata(res.Entries)

if !(len(res.Entries) == 0 && len(test.want) == 0) && !reflect.DeepEqual(res.Entries, test.want) {
Expand All @@ -410,8 +420,6 @@ func TestObjectEntries(t *testing.T) {
if err != nil {
t.Fatal(err)
}

// assert mod time & mime type and clear it afterwards so we can compare
assertMetadata(res.Entries)

if len(res.Entries) != 1 || res.Entries[0] != test.want[offset] {
Expand All @@ -431,8 +439,6 @@ func TestObjectEntries(t *testing.T) {
if err != nil {
t.Fatal(err)
}

// assert mod time & mime type and clear it afterwards so we can compare
assertMetadata(res.Entries)

if len(res.Entries) != 1 || res.Entries[0] != test.want[offset+1] {
Expand All @@ -450,8 +456,6 @@ func TestObjectEntries(t *testing.T) {
if err != nil {
t.Fatal(err)
}

// assert mod time & mime type and clear it afterwards so we can compare
assertMetadata(got)

if !(len(got) == 0 && len(test.want) == 0) && !reflect.DeepEqual(got, test.want) {
Expand Down
2 changes: 2 additions & 0 deletions internal/testing/s3_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ func TestS3Basic(t *testing.T) {
t.Fatal("expected LastModified to be non-zero")
} else if !res.LastModified.After(start.UTC()) {
t.Fatal("expected LastModified to be after the start of our test")
} else if res.ETag == "" {
t.Fatal("expected ETag to be set")
}

// get copied object
Expand Down
7 changes: 3 additions & 4 deletions s3/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ func (s *s3) CopyObject(ctx context.Context, srcBucket, srcKey, dstBucket, dstKe
return gofakes3.CopyObjectResult{}, gofakes3.ErrorMessage(gofakes3.ErrInternal, err.Error())
}
return gofakes3.CopyObjectResult{
ETag: "", // TODO: don't have that
ETag: api.FormatETag(obj.ETag),
LastModified: gofakes3.NewContentTime(obj.ModTime.UTC()),
}, nil
}
Expand All @@ -399,7 +399,7 @@ func (s *s3) UploadPart(ctx context.Context, bucket, object string, id gofakes3.
if err != nil {
return nil, gofakes3.ErrorMessage(gofakes3.ErrInternal, err.Error())
}
return &gofakes3.UploadPartResult{ETag: api.FormatEtag(etag)}, nil
return &gofakes3.UploadPartResult{ETag: api.FormatETag(etag)}, nil
}

func (s *s3) ListMultipartUploads(ctx context.Context, bucket string, marker *gofakes3.UploadListMarker, prefix gofakes3.Prefix, limit int64) (*gofakes3.ListMultipartUploadsResult, error) {
Expand Down Expand Up @@ -486,8 +486,7 @@ func (s *s3) CompleteMultipartUpload(ctx context.Context, bucket, object string,
if err != nil {
return nil, gofakes3.ErrorMessage(gofakes3.ErrInternal, err.Error())
}

return &gofakes3.CompleteMultipartUploadResult{
ETag: api.FormatEtag(resp.ETag),
ETag: api.FormatETag(resp.ETag),
}, nil
}
4 changes: 2 additions & 2 deletions s3/s3.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type bus interface {
DeleteBucket(ctx context.Context, name string) error
ListBuckets(ctx context.Context) (buckets []api.Bucket, err error)

AddObject(ctx context.Context, bucket, path, contractSet string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID, mimeType string) (err error)
AddObject(ctx context.Context, bucket, path, contractSet, eTag, mimeType string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID) (err error)
CopyObject(ctx context.Context, srcBucket, dstBucket, srcPath, dstPath string, opts api.CopyObjectOptions) (om api.ObjectMetadata, err error)
DeleteObject(ctx context.Context, bucket, path string, batch bool) (err error)
Object(ctx context.Context, path string, opts ...api.ObjectsOption) (res api.ObjectsResponse, err error)
Expand All @@ -47,7 +47,7 @@ type bus interface {
type worker interface {
UploadObject(ctx context.Context, r io.Reader, path string, opts ...api.UploadOption) (err error)
GetObject(ctx context.Context, path, bucket string, opts ...api.DownloadObjectOption) (api.GetObjectResponse, error)
UploadMultipartUploadPart(ctx context.Context, r io.Reader, path, uploadID string, partNumber int, opts ...api.UploadOption) (etag string, err error)
UploadMultipartUploadPart(ctx context.Context, r io.Reader, path, uploadID string, partNumber int, opts ...api.UploadOption) (eTag string, err error)
}

func (l *gofakes3Logger) Print(level gofakes3.LogLevel, v ...interface{}) {
Expand Down
28 changes: 18 additions & 10 deletions stores/metadata.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ type (
Size int64

MimeType string `json:"index"`
Etag string `gorm:"index"`
}

dbBucket struct {
Expand Down Expand Up @@ -164,6 +165,7 @@ type (
ObjectModTime time.Time
ObjectMimeType string
ObjectHealth float64
ObjectETag string

// slice
SliceOffset uint32
Expand All @@ -184,11 +186,12 @@ type (

// rawObjectMetadata is used for hydrating object metadata.
rawObjectMetadata struct {
ETag string
Health float64
Name string
Size int64
MimeType string
ModTime datetime
Name string
Size int64
}
)

Expand Down Expand Up @@ -304,11 +307,12 @@ func (s dbSlab) convert() (slab object.Slab, err error) {

func (raw rawObjectMetadata) convert() api.ObjectMetadata {
return api.ObjectMetadata{
ETag: raw.ETag,
Health: raw.Health,
Name: raw.Name,
Size: raw.Size,
MimeType: raw.MimeType,
ModTime: time.Time(raw.ModTime).UTC(),
Name: raw.Name,
Size: raw.Size,
}
}

Expand Down Expand Up @@ -395,11 +399,12 @@ func (raw rawObject) convert() (api.Object, error) {
// return object
return api.Object{
ObjectMetadata: api.ObjectMetadata{
Name: raw[0].ObjectName,
Size: raw[0].ObjectSize,
ETag: raw[0].ObjectETag,
Health: minHealth,
MimeType: raw[0].ObjectMimeType,
ModTime: raw[0].ObjectModTime.UTC(),
Name: raw[0].ObjectName,
Size: raw[0].ObjectSize,
},
Object: object.Object{
Key: key,
Expand Down Expand Up @@ -1015,13 +1020,14 @@ func (s *SQLStore) ObjectEntries(ctx context.Context, bucket, path, prefix, mark
var rows []rawObjectMetadata
query := fmt.Sprintf(`
SELECT
MAX(etag) AS ETag,
MAX(created_at) AS ModTime,
CASE slashindex WHEN 0 THEN %s ELSE %s END AS name,
SUM(size) AS size,
MIN(health) as health,
MAX(mimeType) as MimeType
FROM (
SELECT MAX(objects.created_at) AS created_at, MAX(size) AS size, MIN(slabs.health) as health, MAX(objects.mime_type) as mimeType, SUBSTR(object_id, ?) AS trimmed , INSTR(SUBSTR(object_id, ?), "/") AS slashindex
SELECT MAX(etag) AS etag, MAX(objects.created_at) AS created_at, MAX(size) AS size, MIN(slabs.health) as health, MAX(objects.mime_type) as mimeType, SUBSTR(object_id, ?) AS trimmed , INSTR(SUBSTR(object_id, ?), "/") AS slashindex
FROM objects
INNER JOIN buckets b ON objects.db_bucket_id = b.id AND b.name = ?
LEFT JOIN slices ON objects.id = slices.db_object_id
Expand Down Expand Up @@ -1269,8 +1275,9 @@ func (s *SQLStore) CopyObject(ctx context.Context, srcBucket, dstBucket, srcPath
}

om = api.ObjectMetadata{
Health: srcObjHealth,
MimeType: dstObj.MimeType,
ETag: dstObj.Etag,
Health: srcObjHealth,
ModTime: dstObj.CreatedAt.UTC(),
Name: dstObj.ObjectID,
Size: dstObj.Size,
Expand All @@ -1280,7 +1287,7 @@ func (s *SQLStore) CopyObject(ctx context.Context, srcBucket, dstBucket, srcPath
return
}

func (s *SQLStore) UpdateObject(ctx context.Context, bucket, path, contractSet string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID, mimeType string) error {
func (s *SQLStore) UpdateObject(ctx context.Context, bucket, path, contractSet, ETag, mimeType string, o object.Object, usedContracts map[types.PublicKey]types.FileContractID) error {
s.objectsMu.Lock()
defer s.objectsMu.Unlock()

Expand Down Expand Up @@ -1333,6 +1340,7 @@ func (s *SQLStore) UpdateObject(ctx context.Context, bucket, path, contractSet s
Key: objKey,
Size: o.TotalSize(),
MimeType: mimeType,
Etag: ETag,
}
err = tx.Create(&obj).Error
if err != nil {
Expand Down Expand Up @@ -1697,7 +1705,7 @@ func (s *SQLStore) object(ctx context.Context, txn *gorm.DB, bucket string, path
// accordingly
var rows rawObject
tx := s.db.
Select("o.id as ObjectID, o.key as ObjectKey, o.object_id as ObjectName, o.size as ObjectSize, o.mime_type as ObjectMimeType, o.created_at as ObjectModTime, sli.id as SliceID, sli.offset as SliceOffset, sli.length as SliceLength, sla.id as SlabID, sla.health as SlabHealth, sla.key as SlabKey, sla.min_shards as SlabMinShards, bs.id IS NOT NULL AS SlabBuffered, sec.id as SectorID, sec.root as SectorRoot, sec.latest_host as SectorHost").
Select("o.id as ObjectID, o.key as ObjectKey, o.object_id as ObjectName, o.size as ObjectSize, o.mime_type as ObjectMimeType, o.created_at as ObjectModTime, o.etag as ObjectETag, sli.id as SliceID, sli.offset as SliceOffset, sli.length as SliceLength, sla.id as SlabID, sla.health as SlabHealth, sla.key as SlabKey, sla.min_shards as SlabMinShards, bs.id IS NOT NULL AS SlabBuffered, sec.id as SectorID, sec.root as SectorRoot, sec.latest_host as SectorHost").
Model(&dbObject{}).
Table("objects o").
Joins("INNER JOIN buckets b ON o.db_bucket_id = b.id AND b.name = ?", bucket).
Expand Down
Loading