mirror of
https://github.com/minio/minio.git
synced 2024-12-24 06:05:55 -05:00
Add IsRemote method on FileInfo, ObjectInfo (#12209)
Provides a convenient method to know if an object's contents are in its remote tier.
This commit is contained in:
parent
e948e7cdf6
commit
860bf1bab2
@ -201,12 +201,10 @@ func setObjectHeaders(w http.ResponseWriter, objInfo ObjectInfo, rs *HTTPRangeSp
|
||||
}
|
||||
}
|
||||
}
|
||||
if objInfo.TransitionStatus == lifecycle.TransitionComplete {
|
||||
if objInfo.IsRemote() {
|
||||
// Check if object is being restored. For more information on x-amz-restore header see
|
||||
// https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html#API_HeadObject_ResponseSyntax
|
||||
if onDisk := isRestoredObjectOnDisk(objInfo.UserDefined); !onDisk {
|
||||
w.Header()[xhttp.AmzStorageClass] = []string{objInfo.TransitionTier}
|
||||
}
|
||||
w.Header()[xhttp.AmzStorageClass] = []string{objInfo.TransitionTier}
|
||||
}
|
||||
ruleID, transitionTime := lc.PredictTransitionTime(lifecycle.ObjectOpts{
|
||||
Name: objInfo.Name,
|
||||
|
@ -550,6 +550,24 @@ func putRestoreOpts(bucket, object string, rreq *RestoreObjectRequest, objInfo O
|
||||
|
||||
var errRestoreHDRMalformed = fmt.Errorf("x-amz-restore header malformed")
|
||||
|
||||
// IsRemote returns true if this object version's contents are in its remote
|
||||
// tier.
|
||||
func (fi FileInfo) IsRemote() bool {
|
||||
if fi.TransitionStatus != lifecycle.TransitionComplete {
|
||||
return false
|
||||
}
|
||||
return !isRestoredObjectOnDisk(fi.Metadata)
|
||||
}
|
||||
|
||||
// IsRemote returns true if this object version's contents are in its remote
|
||||
// tier.
|
||||
func (oi ObjectInfo) IsRemote() bool {
|
||||
if oi.TransitionStatus != lifecycle.TransitionComplete {
|
||||
return false
|
||||
}
|
||||
return !isRestoredObjectOnDisk(oi.UserDefined)
|
||||
}
|
||||
|
||||
// restoreObjStatus represents a restore-object's status. It can be either
|
||||
// ongoing or completed.
|
||||
type restoreObjStatus struct {
|
||||
|
@ -23,6 +23,7 @@ import (
|
||||
"time"
|
||||
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/pkg/bucket/lifecycle"
|
||||
)
|
||||
|
||||
// TestParseRestoreObjStatus tests parseRestoreObjStatus
|
||||
@ -155,3 +156,61 @@ func TestIsRestoredObjectOnDisk(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestObjectIsRemote(t *testing.T) {
|
||||
fi := newFileInfo("object", 8, 8)
|
||||
fi.Erasure.Index = 1
|
||||
if !fi.IsValid() {
|
||||
t.Fatalf("unable to get xl meta")
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
meta map[string]string
|
||||
remote bool
|
||||
}{
|
||||
{
|
||||
// restore in progress
|
||||
meta: map[string]string{
|
||||
xhttp.AmzRestore: ongoingRestoreObj().String(),
|
||||
},
|
||||
remote: true,
|
||||
},
|
||||
{
|
||||
// restore completed
|
||||
meta: map[string]string{
|
||||
xhttp.AmzRestore: completedRestoreObj(time.Now().Add(time.Hour)).String(),
|
||||
},
|
||||
remote: false,
|
||||
},
|
||||
{
|
||||
// restore completed but expired
|
||||
meta: map[string]string{
|
||||
xhttp.AmzRestore: completedRestoreObj(time.Now().Add(-time.Hour)).String(),
|
||||
},
|
||||
remote: true,
|
||||
},
|
||||
{
|
||||
// restore never initiated
|
||||
meta: map[string]string{},
|
||||
remote: true,
|
||||
},
|
||||
}
|
||||
for i, tc := range testCases {
|
||||
// Set transition status to complete
|
||||
fi.TransitionStatus = lifecycle.TransitionComplete
|
||||
fi.Metadata = tc.meta
|
||||
if got := fi.IsRemote(); got != tc.remote {
|
||||
t.Fatalf("Test %d.a: expected %v got %v", i+1, tc.remote, got)
|
||||
}
|
||||
oi := fi.ToObjectInfo("bucket", "object")
|
||||
if got := oi.IsRemote(); got != tc.remote {
|
||||
t.Fatalf("Test %d.b: expected %v got %v", i+1, tc.remote, got)
|
||||
}
|
||||
}
|
||||
// Reset transition status; An object that's not transitioned is not remote.
|
||||
fi.TransitionStatus = ""
|
||||
fi.Metadata = nil
|
||||
if got := fi.IsRemote(); got != false {
|
||||
t.Fatalf("Expected object not to be remote but got %v", got)
|
||||
}
|
||||
}
|
||||
|
@ -509,7 +509,7 @@ func (er erasureObjects) healObject(ctx context.Context, bucket string, object s
|
||||
|
||||
// dataDir should be empty when
|
||||
// - transitionStatus is complete and not in restored state
|
||||
if partsMetadata[i].TransitionStatus == lifecycle.TransitionComplete && !isRestoredObjectOnDisk(partsMetadata[i].Metadata) {
|
||||
if partsMetadata[i].IsRemote() {
|
||||
partsMetadata[i].DataDir = ""
|
||||
}
|
||||
// Attempt a rename now from healed data to final location.
|
||||
|
@ -183,16 +183,13 @@ func (er erasureObjects) GetObjectNInfo(ctx context.Context, bucket, object stri
|
||||
ObjInfo: objInfo,
|
||||
}, toObjectErr(errMethodNotAllowed, bucket, object)
|
||||
}
|
||||
if objInfo.TransitionStatus == lifecycle.TransitionComplete {
|
||||
// If transitioned, stream from transition tier unless object is restored locally or restore date is past.
|
||||
if onDisk := isRestoredObjectOnDisk(objInfo.UserDefined); !onDisk {
|
||||
gr, err := getTransitionedObjectReader(ctx, bucket, object, rs, h, objInfo, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
unlockOnDefer = false
|
||||
return gr.WithCleanupFuncs(nsUnlocker), nil
|
||||
if objInfo.IsRemote() {
|
||||
gr, err := getTransitionedObjectReader(ctx, bucket, object, rs, h, objInfo, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
unlockOnDefer = false
|
||||
return gr.WithCleanupFuncs(nsUnlocker), nil
|
||||
}
|
||||
|
||||
fn, off, length, err := NewGetObjectReader(rs, objInfo, opts)
|
||||
|
Loading…
Reference in New Issue
Block a user