github.com/minio/minio@v0.0.0-20240328213742-3f72439b8a27/cmd/xl-storage-free-version.go (about)

     1  // Copyright (c) 2015-2021 MinIO, Inc.
     2  //
     3  // This file is part of MinIO Object Storage stack
     4  //
     5  // This program is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Affero General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // This program is distributed in the hope that it will be useful
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU Affero General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Affero General Public License
    16  // along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17  
    18  package cmd
    19  
    20  import (
    21  	"bytes"
    22  	"fmt"
    23  
    24  	"github.com/google/uuid"
    25  	"github.com/minio/minio/internal/bucket/lifecycle"
    26  )
    27  
    28  const freeVersion = "free-version"
    29  
    30  // InitFreeVersion creates a free-version to track the tiered-content of j. If j has
    31  // no tiered content, it returns false.
    32  func (j xlMetaV2Object) InitFreeVersion(fi FileInfo) (xlMetaV2Version, bool) {
    33  	if fi.SkipTierFreeVersion() {
    34  		return xlMetaV2Version{}, false
    35  	}
    36  	if status, ok := j.MetaSys[ReservedMetadataPrefixLower+TransitionStatus]; ok && bytes.Equal(status, []byte(lifecycle.TransitionComplete)) {
    37  		vID, err := uuid.Parse(fi.TierFreeVersionID())
    38  		if err != nil {
    39  			panic(fmt.Errorf("Invalid Tier Object delete marker versionId %s %v", fi.TierFreeVersionID(), err))
    40  		}
    41  		freeEntry := xlMetaV2Version{Type: DeleteType, WrittenByVersion: globalVersionUnix}
    42  		freeEntry.DeleteMarker = &xlMetaV2DeleteMarker{
    43  			VersionID: vID,
    44  			ModTime:   j.ModTime, // fi.ModTime may be empty
    45  			MetaSys:   make(map[string][]byte),
    46  		}
    47  
    48  		freeEntry.DeleteMarker.MetaSys[ReservedMetadataPrefixLower+freeVersion] = []byte{}
    49  		tierKey := ReservedMetadataPrefixLower + TransitionTier
    50  		tierObjKey := ReservedMetadataPrefixLower + TransitionedObjectName
    51  		tierObjVIDKey := ReservedMetadataPrefixLower + TransitionedVersionID
    52  
    53  		for k, v := range j.MetaSys {
    54  			switch k {
    55  			case tierKey, tierObjKey, tierObjVIDKey:
    56  				freeEntry.DeleteMarker.MetaSys[k] = v
    57  			}
    58  		}
    59  		return freeEntry, true
    60  	}
    61  	return xlMetaV2Version{}, false
    62  }
    63  
    64  // FreeVersion returns true if j represents a free-version, false otherwise.
    65  func (j xlMetaV2DeleteMarker) FreeVersion() bool {
    66  	_, ok := j.MetaSys[ReservedMetadataPrefixLower+freeVersion]
    67  	return ok
    68  }
    69  
    70  // FreeVersion returns true if j represents a free-version, false otherwise.
    71  func (j xlMetaV2Version) FreeVersion() bool {
    72  	if j.Type == DeleteType {
    73  		return j.DeleteMarker.FreeVersion()
    74  	}
    75  	return false
    76  }
    77  
    78  // AddFreeVersion adds a free-version if needed for fi.VersionID version.
    79  // Free-version will be added if fi.VersionID has transitioned.
    80  func (x *xlMetaV2) AddFreeVersion(fi FileInfo) error {
    81  	var uv uuid.UUID
    82  	var err error
    83  	switch fi.VersionID {
    84  	case "", nullVersionID:
    85  	default:
    86  		uv, err = uuid.Parse(fi.VersionID)
    87  		if err != nil {
    88  			return err
    89  		}
    90  	}
    91  
    92  	for i, version := range x.versions {
    93  		if version.header.VersionID != uv || version.header.Type != ObjectType {
    94  			continue
    95  		}
    96  		// if uv has tiered content we add a
    97  		// free-version to track it for asynchronous
    98  		// deletion via scanner.
    99  		ver, err := x.getIdx(i)
   100  		if err != nil {
   101  			return err
   102  		}
   103  
   104  		if freeVersion, toFree := ver.ObjectV2.InitFreeVersion(fi); toFree {
   105  			return x.addVersion(freeVersion)
   106  		}
   107  		return nil
   108  	}
   109  	return nil
   110  }