save MinIO version with each version (8-bytes extra) (#15170)

store MinIO version along with each version in 'xl.meta'
for future purposes, can be used as ways to add specific
code for bug fixes if any.
This commit is contained in:
Harshavardhana 2022-06-27 03:59:41 -07:00 committed by GitHub
parent 7b9b7cef11
commit 6722f58668
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 92 additions and 25 deletions

View File

@ -102,6 +102,11 @@ func init() {
PersistOnFailure: false, PersistOnFailure: false,
} }
t, _ := minioVersionToReleaseTime(Version)
if !t.IsZero() {
globalVersionUnix = uint64(t.Unix())
}
globalIsCICD = env.Get("MINIO_CI_CD", "") != "" || env.Get("CI", "") != "" globalIsCICD = env.Get("MINIO_CI_CD", "") != "" || env.Get("CI", "") != ""
containers := IsKubernetes() || IsDocker() || IsBOSH() || IsDCOS() || IsPCFTile() containers := IsKubernetes() || IsDocker() || IsBOSH() || IsDCOS() || IsPCFTile()

View File

@ -326,6 +326,7 @@ func (er erasureObjects) newMultipartUpload(ctx context.Context, bucket string,
partsMetadata := make([]FileInfo, len(onlineDisks)) partsMetadata := make([]FileInfo, len(onlineDisks))
fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives) fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives)
fi.WrittenByVersion = globalVersionUnix
fi.VersionID = opts.VersionID fi.VersionID = opts.VersionID
if opts.Versioned && fi.VersionID == "" { if opts.Versioned && fi.VersionID == "" {
fi.VersionID = mustGetUUID() fi.VersionID = mustGetUUID()

View File

@ -944,6 +944,7 @@ func (er erasureObjects) putObject(ctx context.Context, bucket string, object st
partsMetadata := make([]FileInfo, len(storageDisks)) partsMetadata := make([]FileInfo, len(storageDisks))
fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives) fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives)
fi.WrittenByVersion = globalVersionUnix
fi.VersionID = opts.VersionID fi.VersionID = opts.VersionID
if opts.Versioned && fi.VersionID == "" { if opts.Versioned && fi.VersionID == "" {
fi.VersionID = mustGetUUID() fi.VersionID = mustGetUUID()

View File

@ -941,6 +941,7 @@ func (es *erasureSingle) putObject(ctx context.Context, bucket string, object st
partsMetadata := make([]FileInfo, len(storageDisks)) partsMetadata := make([]FileInfo, len(storageDisks))
fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives) fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives)
fi.WrittenByVersion = globalVersionUnix
fi.VersionID = opts.VersionID fi.VersionID = opts.VersionID
if opts.Versioned && fi.VersionID == "" { if opts.Versioned && fi.VersionID == "" {
fi.VersionID = mustGetUUID() fi.VersionID = mustGetUUID()
@ -2070,6 +2071,7 @@ func (es *erasureSingle) newMultipartUpload(ctx context.Context, bucket string,
partsMetadata := make([]FileInfo, len(onlineDisks)) partsMetadata := make([]FileInfo, len(onlineDisks))
fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives) fi := newFileInfo(pathJoin(bucket, object), dataDrives, parityDrives)
fi.WrittenByVersion = globalVersionUnix
fi.VersionID = opts.VersionID fi.VersionID = opts.VersionID
if opts.Versioned && fi.VersionID == "" { if opts.Versioned && fi.VersionID == "" {
fi.VersionID = mustGetUUID() fi.VersionID = mustGetUUID()

View File

@ -373,6 +373,9 @@ var (
globalObjectPerfBucket = "minio-perf-test-tmp-bucket" globalObjectPerfBucket = "minio-perf-test-tmp-bucket"
globalObjectPerfUserMetadata = "X-Amz-Meta-Minio-Object-Perf" // Clients can set this to bypass S3 API service freeze. Used by object pref tests. globalObjectPerfUserMetadata = "X-Amz-Meta-Minio-Object-Perf" // Clients can set this to bypass S3 API service freeze. Used by object pref tests.
// MinIO version unix timestamp
globalVersionUnix uint64
// Add new variable global values here. // Add new variable global values here.
) )

View File

@ -176,6 +176,10 @@ type FileInfo struct {
// File mode bits. // File mode bits.
Mode uint32 `msg:"m"` Mode uint32 `msg:"m"`
// WrittenByVersion is the unix time stamp of the MinIO
// version that created this version of the object.
WrittenByVersion uint64 `msg:"wv"`
// File metadata // File metadata
Metadata map[string]string `msg:"meta"` Metadata map[string]string `msg:"meta"`

View File

@ -550,8 +550,8 @@ func (z *FileInfo) DecodeMsg(dc *msgp.Reader) (err error) {
err = msgp.WrapError(err) err = msgp.WrapError(err)
return return
} }
if zb0001 != 26 { if zb0001 != 27 {
err = msgp.ArrayError{Wanted: 26, Got: zb0001} err = msgp.ArrayError{Wanted: 27, Got: zb0001}
return return
} }
z.Volume, err = dc.ReadString() z.Volume, err = dc.ReadString()
@ -629,6 +629,11 @@ func (z *FileInfo) DecodeMsg(dc *msgp.Reader) (err error) {
err = msgp.WrapError(err, "Mode") err = msgp.WrapError(err, "Mode")
return return
} }
z.WrittenByVersion, err = dc.ReadUint64()
if err != nil {
err = msgp.WrapError(err, "WrittenByVersion")
return
}
var zb0002 uint32 var zb0002 uint32
zb0002, err = dc.ReadMapHeader() zb0002, err = dc.ReadMapHeader()
if err != nil { if err != nil {
@ -726,8 +731,8 @@ func (z *FileInfo) DecodeMsg(dc *msgp.Reader) (err error) {
// EncodeMsg implements msgp.Encodable // EncodeMsg implements msgp.Encodable
func (z *FileInfo) EncodeMsg(en *msgp.Writer) (err error) { func (z *FileInfo) EncodeMsg(en *msgp.Writer) (err error) {
// array header, size 26 // array header, size 27
err = en.Append(0xdc, 0x0, 0x1a) err = en.Append(0xdc, 0x0, 0x1b)
if err != nil { if err != nil {
return return
} }
@ -806,6 +811,11 @@ func (z *FileInfo) EncodeMsg(en *msgp.Writer) (err error) {
err = msgp.WrapError(err, "Mode") err = msgp.WrapError(err, "Mode")
return return
} }
err = en.WriteUint64(z.WrittenByVersion)
if err != nil {
err = msgp.WrapError(err, "WrittenByVersion")
return
}
err = en.WriteMapHeader(uint32(len(z.Metadata))) err = en.WriteMapHeader(uint32(len(z.Metadata)))
if err != nil { if err != nil {
err = msgp.WrapError(err, "Metadata") err = msgp.WrapError(err, "Metadata")
@ -886,8 +896,8 @@ func (z *FileInfo) EncodeMsg(en *msgp.Writer) (err error) {
// MarshalMsg implements msgp.Marshaler // MarshalMsg implements msgp.Marshaler
func (z *FileInfo) MarshalMsg(b []byte) (o []byte, err error) { func (z *FileInfo) MarshalMsg(b []byte) (o []byte, err error) {
o = msgp.Require(b, z.Msgsize()) o = msgp.Require(b, z.Msgsize())
// array header, size 26 // array header, size 27
o = append(o, 0xdc, 0x0, 0x1a) o = append(o, 0xdc, 0x0, 0x1b)
o = msgp.AppendString(o, z.Volume) o = msgp.AppendString(o, z.Volume)
o = msgp.AppendString(o, z.Name) o = msgp.AppendString(o, z.Name)
o = msgp.AppendString(o, z.VersionID) o = msgp.AppendString(o, z.VersionID)
@ -903,6 +913,7 @@ func (z *FileInfo) MarshalMsg(b []byte) (o []byte, err error) {
o = msgp.AppendTime(o, z.ModTime) o = msgp.AppendTime(o, z.ModTime)
o = msgp.AppendInt64(o, z.Size) o = msgp.AppendInt64(o, z.Size)
o = msgp.AppendUint32(o, z.Mode) o = msgp.AppendUint32(o, z.Mode)
o = msgp.AppendUint64(o, z.WrittenByVersion)
o = msgp.AppendMapHeader(o, uint32(len(z.Metadata))) o = msgp.AppendMapHeader(o, uint32(len(z.Metadata)))
for za0001, za0002 := range z.Metadata { for za0001, za0002 := range z.Metadata {
o = msgp.AppendString(o, za0001) o = msgp.AppendString(o, za0001)
@ -944,8 +955,8 @@ func (z *FileInfo) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err) err = msgp.WrapError(err)
return return
} }
if zb0001 != 26 { if zb0001 != 27 {
err = msgp.ArrayError{Wanted: 26, Got: zb0001} err = msgp.ArrayError{Wanted: 27, Got: zb0001}
return return
} }
z.Volume, bts, err = msgp.ReadStringBytes(bts) z.Volume, bts, err = msgp.ReadStringBytes(bts)
@ -1023,6 +1034,11 @@ func (z *FileInfo) UnmarshalMsg(bts []byte) (o []byte, err error) {
err = msgp.WrapError(err, "Mode") err = msgp.WrapError(err, "Mode")
return return
} }
z.WrittenByVersion, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "WrittenByVersion")
return
}
var zb0002 uint32 var zb0002 uint32
zb0002, bts, err = msgp.ReadMapHeaderBytes(bts) zb0002, bts, err = msgp.ReadMapHeaderBytes(bts)
if err != nil { if err != nil {
@ -1121,7 +1137,7 @@ func (z *FileInfo) UnmarshalMsg(bts []byte) (o []byte, err error) {
// Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message
func (z *FileInfo) Msgsize() (s int) { func (z *FileInfo) Msgsize() (s int) {
s = 3 + msgp.StringPrefixSize + len(z.Volume) + msgp.StringPrefixSize + len(z.Name) + msgp.StringPrefixSize + len(z.VersionID) + msgp.BoolSize + msgp.BoolSize + msgp.StringPrefixSize + len(z.TransitionStatus) + msgp.StringPrefixSize + len(z.TransitionedObjName) + msgp.StringPrefixSize + len(z.TransitionTier) + msgp.StringPrefixSize + len(z.TransitionVersionID) + msgp.BoolSize + msgp.StringPrefixSize + len(z.DataDir) + msgp.BoolSize + msgp.TimeSize + msgp.Int64Size + msgp.Uint32Size + msgp.MapHeaderSize s = 3 + msgp.StringPrefixSize + len(z.Volume) + msgp.StringPrefixSize + len(z.Name) + msgp.StringPrefixSize + len(z.VersionID) + msgp.BoolSize + msgp.BoolSize + msgp.StringPrefixSize + len(z.TransitionStatus) + msgp.StringPrefixSize + len(z.TransitionedObjName) + msgp.StringPrefixSize + len(z.TransitionTier) + msgp.StringPrefixSize + len(z.TransitionVersionID) + msgp.BoolSize + msgp.StringPrefixSize + len(z.DataDir) + msgp.BoolSize + msgp.TimeSize + msgp.Int64Size + msgp.Uint32Size + msgp.Uint64Size + msgp.MapHeaderSize
if z.Metadata != nil { if z.Metadata != nil {
for za0001, za0002 := range z.Metadata { for za0001, za0002 := range z.Metadata {
_ = za0002 _ = za0002

View File

@ -1,4 +1,4 @@
// Copyright (c) 2015-2021 MinIO, Inc. // Copyright (c) 2015-2022 MinIO, Inc.
// //
// This file is part of MinIO Object Storage stack // This file is part of MinIO Object Storage stack
// //
@ -18,7 +18,7 @@
package cmd package cmd
const ( const (
storageRESTVersion = "v45" // Added ReadXL API storageRESTVersion = "v46" // Added MinIO version to FileInfo
storageRESTVersionPrefix = SlashSeparator + storageRESTVersion storageRESTVersionPrefix = SlashSeparator + storageRESTVersion
storageRESTPrefix = minioReservedBucketPath + "/storage" storageRESTPrefix = minioReservedBucketPath + "/storage"
) )

View File

@ -178,10 +178,11 @@ type xlMetaV2Object struct {
// on what Type field carries, it is imperative for the caller // on what Type field carries, it is imperative for the caller
// to verify which journal type first before accessing rest of the fields. // to verify which journal type first before accessing rest of the fields.
type xlMetaV2Version struct { type xlMetaV2Version struct {
Type VersionType `json:"Type" msg:"Type"` Type VersionType `json:"Type" msg:"Type"`
ObjectV1 *xlMetaV1Object `json:"V1Obj,omitempty" msg:"V1Obj,omitempty"` ObjectV1 *xlMetaV1Object `json:"V1Obj,omitempty" msg:"V1Obj,omitempty"`
ObjectV2 *xlMetaV2Object `json:"V2Obj,omitempty" msg:"V2Obj,omitempty"` ObjectV2 *xlMetaV2Object `json:"V2Obj,omitempty" msg:"V2Obj,omitempty"`
DeleteMarker *xlMetaV2DeleteMarker `json:"DelObj,omitempty" msg:"DelObj,omitempty"` DeleteMarker *xlMetaV2DeleteMarker `json:"DelObj,omitempty" msg:"DelObj,omitempty"`
WrittenByVersion uint64 `msg:"v"` // Tracks written by MinIO version
} }
// xlFlags contains flags on the object. // xlFlags contains flags on the object.
@ -409,16 +410,22 @@ func (j xlMetaV2Version) getVersionID() [16]byte {
} }
// ToFileInfo returns FileInfo of the underlying type. // ToFileInfo returns FileInfo of the underlying type.
func (j *xlMetaV2Version) ToFileInfo(volume, path string) (FileInfo, error) { func (j *xlMetaV2Version) ToFileInfo(volume, path string) (fi FileInfo, err error) {
if j == nil {
return fi, errFileNotFound
}
switch j.Type { switch j.Type {
case ObjectType: case ObjectType:
return j.ObjectV2.ToFileInfo(volume, path) fi, err = j.ObjectV2.ToFileInfo(volume, path)
case DeleteType: case DeleteType:
return j.DeleteMarker.ToFileInfo(volume, path) fi, err = j.DeleteMarker.ToFileInfo(volume, path)
case LegacyType: case LegacyType:
return j.ObjectV1.ToFileInfo(volume, path) fi, err = j.ObjectV1.ToFileInfo(volume, path)
default:
return fi, errFileNotFound
} }
return FileInfo{}, errFileNotFound fi.WrittenByVersion = j.WrittenByVersion
return fi, err
} }
const ( const (
@ -1424,7 +1431,9 @@ func (x *xlMetaV2) AddVersion(fi FileInfo) error {
} }
} }
ventry := xlMetaV2Version{} ventry := xlMetaV2Version{
WrittenByVersion: fi.WrittenByVersion,
}
if fi.Deleted { if fi.Deleted {
ventry.Type = DeleteType ventry.Type = DeleteType

View File

@ -1774,6 +1774,12 @@ func (z *xlMetaV2Version) DecodeMsg(dc *msgp.Reader) (err error) {
return return
} }
} }
case "v":
z.WrittenByVersion, err = dc.ReadUint64()
if err != nil {
err = msgp.WrapError(err, "WrittenByVersion")
return
}
default: default:
err = dc.Skip() err = dc.Skip()
if err != nil { if err != nil {
@ -1788,8 +1794,8 @@ func (z *xlMetaV2Version) DecodeMsg(dc *msgp.Reader) (err error) {
// EncodeMsg implements msgp.Encodable // EncodeMsg implements msgp.Encodable
func (z *xlMetaV2Version) EncodeMsg(en *msgp.Writer) (err error) { func (z *xlMetaV2Version) EncodeMsg(en *msgp.Writer) (err error) {
// omitempty: check for empty values // omitempty: check for empty values
zb0001Len := uint32(4) zb0001Len := uint32(5)
var zb0001Mask uint8 /* 4 bits */ var zb0001Mask uint8 /* 5 bits */
if z.ObjectV1 == nil { if z.ObjectV1 == nil {
zb0001Len-- zb0001Len--
zb0001Mask |= 0x2 zb0001Mask |= 0x2
@ -1877,6 +1883,16 @@ func (z *xlMetaV2Version) EncodeMsg(en *msgp.Writer) (err error) {
} }
} }
} }
// write "v"
err = en.Append(0xa1, 0x76)
if err != nil {
return
}
err = en.WriteUint64(z.WrittenByVersion)
if err != nil {
err = msgp.WrapError(err, "WrittenByVersion")
return
}
return return
} }
@ -1884,8 +1900,8 @@ func (z *xlMetaV2Version) EncodeMsg(en *msgp.Writer) (err error) {
func (z *xlMetaV2Version) MarshalMsg(b []byte) (o []byte, err error) { func (z *xlMetaV2Version) MarshalMsg(b []byte) (o []byte, err error) {
o = msgp.Require(b, z.Msgsize()) o = msgp.Require(b, z.Msgsize())
// omitempty: check for empty values // omitempty: check for empty values
zb0001Len := uint32(4) zb0001Len := uint32(5)
var zb0001Mask uint8 /* 4 bits */ var zb0001Mask uint8 /* 5 bits */
if z.ObjectV1 == nil { if z.ObjectV1 == nil {
zb0001Len-- zb0001Len--
zb0001Mask |= 0x2 zb0001Mask |= 0x2
@ -1945,6 +1961,9 @@ func (z *xlMetaV2Version) MarshalMsg(b []byte) (o []byte, err error) {
} }
} }
} }
// string "v"
o = append(o, 0xa1, 0x76)
o = msgp.AppendUint64(o, z.WrittenByVersion)
return return
} }
@ -2027,6 +2046,12 @@ func (z *xlMetaV2Version) UnmarshalMsg(bts []byte) (o []byte, err error) {
return return
} }
} }
case "v":
z.WrittenByVersion, bts, err = msgp.ReadUint64Bytes(bts)
if err != nil {
err = msgp.WrapError(err, "WrittenByVersion")
return
}
default: default:
bts, err = msgp.Skip(bts) bts, err = msgp.Skip(bts)
if err != nil { if err != nil {
@ -2059,6 +2084,7 @@ func (z *xlMetaV2Version) Msgsize() (s int) {
} else { } else {
s += z.DeleteMarker.Msgsize() s += z.DeleteMarker.Msgsize()
} }
s += 2 + msgp.Uint64Size
return return
} }