mirror of
https://github.com/pgsty/minio.git
synced 2026-08-09 07:43:29 +03:00
migrate all bucket metadata into a single file (#9586)
this is a major overhaul by migrating off all bucket metadata related configs into a single object '.metadata.bin' this allows us for faster bootups across 1000's of buckets and as well as keeps the code simple enough for future work and additions. Additionally also fixes #9396, #9394
This commit is contained in:
+69
-91
@@ -29,15 +29,13 @@ import (
|
||||
"github.com/minio/minio-go/v6/pkg/tags"
|
||||
xhttp "github.com/minio/minio/cmd/http"
|
||||
"github.com/minio/minio/cmd/logger"
|
||||
bucketsse "github.com/minio/minio/pkg/bucket/encryption"
|
||||
"github.com/minio/minio/pkg/bucket/lifecycle"
|
||||
objectlock "github.com/minio/minio/pkg/bucket/object/lock"
|
||||
"github.com/minio/minio/pkg/bucket/policy"
|
||||
"github.com/minio/minio/pkg/madmin"
|
||||
"github.com/minio/minio/pkg/sync/errgroup"
|
||||
)
|
||||
|
||||
type xlZones struct {
|
||||
GatewayUnsupported
|
||||
|
||||
zones []*xlSets
|
||||
}
|
||||
|
||||
@@ -323,13 +321,14 @@ func (z *xlZones) MakeBucketWithLocation(ctx context.Context, bucket, location s
|
||||
if err := z.zones[0].MakeBucketWithLocation(ctx, bucket, location, lockEnabled); err != nil {
|
||||
return err
|
||||
}
|
||||
if lockEnabled {
|
||||
meta := newBucketMetadata(bucket)
|
||||
meta.LockEnabled = lockEnabled
|
||||
if err := meta.save(ctx, z); err != nil {
|
||||
return toObjectErr(err, bucket)
|
||||
}
|
||||
|
||||
// If it doesn't exist we get a new, so ignore errors
|
||||
meta, _ := globalBucketMetadataSys.Get(bucket)
|
||||
meta.ObjectLockConfigurationXML = defaultBucketObjectLockConfig
|
||||
if err := meta.Save(ctx, z); err != nil {
|
||||
return toObjectErr(err, bucket)
|
||||
}
|
||||
globalBucketMetadataSys.Set(bucket, meta)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -351,13 +350,13 @@ func (z *xlZones) MakeBucketWithLocation(ctx context.Context, bucket, location s
|
||||
}
|
||||
}
|
||||
|
||||
if lockEnabled {
|
||||
meta := newBucketMetadata(bucket)
|
||||
meta.LockEnabled = lockEnabled
|
||||
if err := meta.save(ctx, z); err != nil {
|
||||
return toObjectErr(err, bucket)
|
||||
}
|
||||
// If it doesn't exist we get a new, so ignore errors
|
||||
meta, _ := globalBucketMetadataSys.Get(bucket)
|
||||
meta.ObjectLockConfigurationXML = defaultBucketObjectLockConfig
|
||||
if err := meta.Save(ctx, z); err != nil {
|
||||
return toObjectErr(err, bucket)
|
||||
}
|
||||
globalBucketMetadataSys.Set(bucket, meta)
|
||||
|
||||
// Success.
|
||||
return nil
|
||||
@@ -980,9 +979,14 @@ func (z *xlZones) ListObjects(ctx context.Context, bucket, prefix, marker, delim
|
||||
}
|
||||
|
||||
func (z *xlZones) ListMultipartUploads(ctx context.Context, bucket, prefix, keyMarker, uploadIDMarker, delimiter string, maxUploads int) (ListMultipartsInfo, error) {
|
||||
if err := checkListMultipartArgs(ctx, bucket, prefix, keyMarker, uploadIDMarker, delimiter, z); err != nil {
|
||||
return ListMultipartsInfo{}, err
|
||||
}
|
||||
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].ListMultipartUploads(ctx, bucket, prefix, keyMarker, uploadIDMarker, delimiter, maxUploads)
|
||||
}
|
||||
|
||||
var zoneResult = ListMultipartsInfo{}
|
||||
zoneResult.MaxUploads = maxUploads
|
||||
zoneResult.KeyMarker = keyMarker
|
||||
@@ -1001,6 +1005,10 @@ func (z *xlZones) ListMultipartUploads(ctx context.Context, bucket, prefix, keyM
|
||||
|
||||
// Initiate a new multipart upload on a hashedSet based on object name.
|
||||
func (z *xlZones) NewMultipartUpload(ctx context.Context, bucket, object string, opts ObjectOptions) (string, error) {
|
||||
if err := checkNewMultipartArgs(ctx, bucket, object, z); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].NewMultipartUpload(ctx, bucket, object, opts)
|
||||
}
|
||||
@@ -1009,12 +1017,20 @@ func (z *xlZones) NewMultipartUpload(ctx context.Context, bucket, object string,
|
||||
|
||||
// Copies a part of an object from source hashedSet to destination hashedSet.
|
||||
func (z *xlZones) CopyObjectPart(ctx context.Context, srcBucket, srcObject, destBucket, destObject string, uploadID string, partID int, startOffset int64, length int64, srcInfo ObjectInfo, srcOpts, dstOpts ObjectOptions) (PartInfo, error) {
|
||||
if err := checkNewMultipartArgs(ctx, srcBucket, srcObject, z); err != nil {
|
||||
return PartInfo{}, err
|
||||
}
|
||||
|
||||
return z.PutObjectPart(ctx, destBucket, destObject, uploadID, partID,
|
||||
NewPutObjReader(srcInfo.Reader, nil, nil), dstOpts)
|
||||
}
|
||||
|
||||
// PutObjectPart - writes part of an object to hashedSet based on the object name.
|
||||
func (z *xlZones) PutObjectPart(ctx context.Context, bucket, object, uploadID string, partID int, data *PutObjReader, opts ObjectOptions) (PartInfo, error) {
|
||||
if err := checkPutObjectPartArgs(ctx, bucket, object, z); err != nil {
|
||||
return PartInfo{}, err
|
||||
}
|
||||
|
||||
uploadIDLock := z.NewNSLock(ctx, bucket, pathJoin(object, uploadID))
|
||||
if err := uploadIDLock.GetLock(globalOperationTimeout); err != nil {
|
||||
return PartInfo{}, err
|
||||
@@ -1043,6 +1059,10 @@ func (z *xlZones) PutObjectPart(ctx context.Context, bucket, object, uploadID st
|
||||
|
||||
// ListObjectParts - lists all uploaded parts to an object in hashedSet.
|
||||
func (z *xlZones) ListObjectParts(ctx context.Context, bucket, object, uploadID string, partNumberMarker int, maxParts int, opts ObjectOptions) (ListPartsInfo, error) {
|
||||
if err := checkListPartsArgs(ctx, bucket, object, z); err != nil {
|
||||
return ListPartsInfo{}, err
|
||||
}
|
||||
|
||||
uploadIDLock := z.NewNSLock(ctx, bucket, pathJoin(object, uploadID))
|
||||
if err := uploadIDLock.GetRLock(globalOperationTimeout); err != nil {
|
||||
return ListPartsInfo{}, err
|
||||
@@ -1070,6 +1090,10 @@ func (z *xlZones) ListObjectParts(ctx context.Context, bucket, object, uploadID
|
||||
|
||||
// Aborts an in-progress multipart operation on hashedSet based on the object name.
|
||||
func (z *xlZones) AbortMultipartUpload(ctx context.Context, bucket, object, uploadID string) error {
|
||||
if err := checkAbortMultipartArgs(ctx, bucket, object, z); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
uploadIDLock := z.NewNSLock(ctx, bucket, pathJoin(object, uploadID))
|
||||
if err := uploadIDLock.GetLock(globalOperationTimeout); err != nil {
|
||||
return err
|
||||
@@ -1079,6 +1103,7 @@ func (z *xlZones) AbortMultipartUpload(ctx context.Context, bucket, object, uplo
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].AbortMultipartUpload(ctx, bucket, object, uploadID)
|
||||
}
|
||||
|
||||
for _, zone := range z.zones {
|
||||
result, err := zone.ListMultipartUploads(ctx, bucket, object, "", "", "", maxObjectList)
|
||||
if err != nil {
|
||||
@@ -1097,6 +1122,10 @@ func (z *xlZones) AbortMultipartUpload(ctx context.Context, bucket, object, uplo
|
||||
|
||||
// CompleteMultipartUpload - completes a pending multipart transaction, on hashedSet based on object name.
|
||||
func (z *xlZones) CompleteMultipartUpload(ctx context.Context, bucket, object, uploadID string, uploadedParts []CompletePart, opts ObjectOptions) (objInfo ObjectInfo, err error) {
|
||||
if err = checkCompleteMultipartArgs(ctx, bucket, object, z); err != nil {
|
||||
return objInfo, err
|
||||
}
|
||||
|
||||
// Hold read-locks to verify uploaded parts, also disallows
|
||||
// parallel part uploads as well.
|
||||
uploadIDLock := z.NewNSLock(ctx, bucket, pathJoin(object, uploadID))
|
||||
@@ -1141,7 +1170,15 @@ func (z *xlZones) CompleteMultipartUpload(ctx context.Context, bucket, object, u
|
||||
// GetBucketInfo - returns bucket info from one of the erasure coded zones.
|
||||
func (z *xlZones) GetBucketInfo(ctx context.Context, bucket string) (bucketInfo BucketInfo, err error) {
|
||||
if z.SingleZone() {
|
||||
return z.zones[0].GetBucketInfo(ctx, bucket)
|
||||
bucketInfo, err = z.zones[0].GetBucketInfo(ctx, bucket)
|
||||
if err != nil {
|
||||
return bucketInfo, err
|
||||
}
|
||||
meta, err := globalBucketMetadataSys.Get(bucket)
|
||||
if err == nil {
|
||||
bucketInfo.Created = meta.Created
|
||||
}
|
||||
return bucketInfo, nil
|
||||
}
|
||||
for _, zone := range z.zones {
|
||||
bucketInfo, err = zone.GetBucketInfo(ctx, bucket)
|
||||
@@ -1151,6 +1188,10 @@ func (z *xlZones) GetBucketInfo(ctx context.Context, bucket string) (bucketInfo
|
||||
}
|
||||
return bucketInfo, err
|
||||
}
|
||||
meta, err := globalBucketMetadataSys.Get(bucket)
|
||||
if err == nil {
|
||||
bucketInfo.Created = meta.Created
|
||||
}
|
||||
return bucketInfo, nil
|
||||
}
|
||||
return bucketInfo, BucketNotFound{
|
||||
@@ -1158,76 +1199,6 @@ func (z *xlZones) GetBucketInfo(ctx context.Context, bucket string) (bucketInfo
|
||||
}
|
||||
}
|
||||
|
||||
// SetBucketPolicy persist the new policy on the bucket.
|
||||
func (z *xlZones) SetBucketPolicy(ctx context.Context, bucket string, policy *policy.Policy) error {
|
||||
return savePolicyConfig(ctx, z, bucket, policy)
|
||||
}
|
||||
|
||||
// GetBucketPolicy will return a policy on a bucket
|
||||
func (z *xlZones) GetBucketPolicy(ctx context.Context, bucket string) (*policy.Policy, error) {
|
||||
return getPolicyConfig(z, bucket)
|
||||
}
|
||||
|
||||
// DeleteBucketPolicy deletes all policies on bucket
|
||||
func (z *xlZones) DeleteBucketPolicy(ctx context.Context, bucket string) error {
|
||||
return removePolicyConfig(ctx, z, bucket)
|
||||
}
|
||||
|
||||
// SetBucketLifecycle zones lifecycle on bucket
|
||||
func (z *xlZones) SetBucketLifecycle(ctx context.Context, bucket string, lifecycle *lifecycle.Lifecycle) error {
|
||||
return saveLifecycleConfig(ctx, z, bucket, lifecycle)
|
||||
}
|
||||
|
||||
// GetBucketLifecycle will get lifecycle on bucket
|
||||
func (z *xlZones) GetBucketLifecycle(ctx context.Context, bucket string) (*lifecycle.Lifecycle, error) {
|
||||
return getLifecycleConfig(z, bucket)
|
||||
}
|
||||
|
||||
// DeleteBucketLifecycle deletes all lifecycle on bucket
|
||||
func (z *xlZones) DeleteBucketLifecycle(ctx context.Context, bucket string) error {
|
||||
return removeLifecycleConfig(ctx, z, bucket)
|
||||
}
|
||||
|
||||
// GetBucketSSEConfig returns bucket encryption config on given bucket
|
||||
func (z *xlZones) GetBucketSSEConfig(ctx context.Context, bucket string) (*bucketsse.BucketSSEConfig, error) {
|
||||
return getBucketSSEConfig(z, bucket)
|
||||
}
|
||||
|
||||
// SetBucketSSEConfig sets bucket encryption config on given bucket
|
||||
func (z *xlZones) SetBucketSSEConfig(ctx context.Context, bucket string, config *bucketsse.BucketSSEConfig) error {
|
||||
return saveBucketSSEConfig(ctx, z, bucket, config)
|
||||
}
|
||||
|
||||
// SetBucketObjectLockConfig enables/clears default object lock configuration
|
||||
func (z *xlZones) SetBucketObjectLockConfig(ctx context.Context, bucket string, config *objectlock.Config) error {
|
||||
return saveBucketObjectLockConfig(ctx, z, bucket, config)
|
||||
}
|
||||
|
||||
// GetBucketObjectLockConfig - returns current defaults for object lock configuration
|
||||
func (z *xlZones) GetBucketObjectLockConfig(ctx context.Context, bucket string) (*objectlock.Config, error) {
|
||||
return readBucketObjectLockConfig(ctx, z, bucket)
|
||||
}
|
||||
|
||||
// SetBucketTagging sets bucket tags on given bucket
|
||||
func (z *xlZones) SetBucketTagging(ctx context.Context, bucket string, t *tags.Tags) error {
|
||||
return saveBucketTagging(ctx, z, bucket, t)
|
||||
}
|
||||
|
||||
// GetBucketTagging get bucket tags set on given bucket
|
||||
func (z *xlZones) GetBucketTagging(ctx context.Context, bucket string) (*tags.Tags, error) {
|
||||
return readBucketTagging(ctx, z, bucket)
|
||||
}
|
||||
|
||||
// DeleteBucketTagging delete bucket tags set if any.
|
||||
func (z *xlZones) DeleteBucketTagging(ctx context.Context, bucket string) error {
|
||||
return deleteBucketTagging(ctx, z, bucket)
|
||||
}
|
||||
|
||||
// DeleteBucketSSEConfig deletes bucket encryption config on given bucket
|
||||
func (z *xlZones) DeleteBucketSSEConfig(ctx context.Context, bucket string) error {
|
||||
return removeBucketSSEConfig(ctx, z, bucket)
|
||||
}
|
||||
|
||||
// IsNotificationSupported returns whether bucket notification is applicable for this layer.
|
||||
func (z *xlZones) IsNotificationSupported() bool {
|
||||
return true
|
||||
@@ -1321,13 +1292,11 @@ func (z *xlZones) ListBuckets(ctx context.Context) (buckets []BucketInfo, err er
|
||||
return nil, err
|
||||
}
|
||||
for i := range buckets {
|
||||
meta, err := loadBucketMetadata(ctx, z, buckets[i].Name)
|
||||
meta, err := globalBucketMetadataSys.Get(buckets[i].Name)
|
||||
if err == nil {
|
||||
buckets[i].Created = meta.Created
|
||||
}
|
||||
if err != errMetaDataConverted {
|
||||
logger.LogIf(ctx, err)
|
||||
}
|
||||
globalBucketMetadataSys.Set(buckets[i].Name, meta)
|
||||
}
|
||||
return buckets, nil
|
||||
}
|
||||
@@ -1544,6 +1513,15 @@ func (z *xlZones) ListBucketsHeal(ctx context.Context) ([]BucketInfo, error) {
|
||||
}
|
||||
healBuckets = append(healBuckets, bucketsInfo...)
|
||||
}
|
||||
|
||||
for i := range healBuckets {
|
||||
meta, err := globalBucketMetadataSys.Get(healBuckets[i].Name)
|
||||
if err == nil {
|
||||
healBuckets[i].Created = meta.Created
|
||||
}
|
||||
globalBucketMetadataSys.Set(healBuckets[i].Name, meta)
|
||||
}
|
||||
|
||||
return healBuckets, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user