| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | // Copyright (c) 2015-2021 MinIO, Inc.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This file is part of MinIO Object Storage stack
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU Affero General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or
 | 
					
						
							|  |  |  | // (at your option) any later version.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU Affero General Public License for more details.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // You should have received a copy of the GNU Affero General Public License
 | 
					
						
							|  |  |  | // along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package cmd | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-06-02 05:59:40 +08:00
										 |  |  | 	"github.com/minio/minio/internal/bucket/lifecycle" | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // objSweeper determines if a transitioned object needs to be removed from the remote tier.
 | 
					
						
							|  |  |  | // A typical usage would be like,
 | 
					
						
							|  |  |  | // os := newObjSweeper(bucket, object)
 | 
					
						
							|  |  |  | // // Perform a ObjectLayer.GetObjectInfo to fetch object version information
 | 
					
						
							|  |  |  | // goiOpts := os.GetOpts()
 | 
					
						
							|  |  |  | // gerr := objAPI.GetObjectInfo(ctx, bucket, object, goiOpts)
 | 
					
						
							|  |  |  | // if gerr == nil {
 | 
					
						
							|  |  |  | //    os.SetTransitionState(goi)
 | 
					
						
							|  |  |  | // }
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // // After the overwriting object operation is complete.
 | 
					
						
							|  |  |  | // if jentry, ok := os.ShouldRemoveRemoteObject(); ok {
 | 
					
						
							|  |  |  | //     err := globalTierJournal.AddEntry(jentry)
 | 
					
						
							|  |  |  | //     logger.LogIf(ctx, err)
 | 
					
						
							|  |  |  | // }
 | 
					
						
							|  |  |  | type objSweeper struct { | 
					
						
							| 
									
										
										
										
											2021-06-04 05:26:51 +08:00
										 |  |  | 	Object              string | 
					
						
							|  |  |  | 	Bucket              string | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | 	VersionID           string // version ID set by application, applies only to DeleteObject and DeleteObjects APIs
 | 
					
						
							| 
									
										
										
										
											2021-06-04 05:26:51 +08:00
										 |  |  | 	Versioned           bool | 
					
						
							|  |  |  | 	Suspended           bool | 
					
						
							|  |  |  | 	TransitionStatus    string | 
					
						
							|  |  |  | 	TransitionTier      string | 
					
						
							|  |  |  | 	TransitionVersionID string | 
					
						
							|  |  |  | 	RemoteObject        string | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // newObjSweeper returns an objSweeper for a given bucket and object.
 | 
					
						
							|  |  |  | // It initializes the versioning information using bucket name.
 | 
					
						
							|  |  |  | func newObjSweeper(bucket, object string) *objSweeper { | 
					
						
							|  |  |  | 	return &objSweeper{ | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | 		Object: object, | 
					
						
							|  |  |  | 		Bucket: bucket, | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | // WithVersion sets the version ID from v
 | 
					
						
							|  |  |  | func (os *objSweeper) WithVersion(vid string) *objSweeper { | 
					
						
							|  |  |  | 	os.VersionID = vid | 
					
						
							|  |  |  | 	return os | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | // WithVersioning sets bucket versioning for sweeper.
 | 
					
						
							|  |  |  | func (os *objSweeper) WithVersioning(versioned, suspended bool) *objSweeper { | 
					
						
							|  |  |  | 	os.Versioned = versioned | 
					
						
							|  |  |  | 	os.Suspended = suspended | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	return os | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // GetOpts returns ObjectOptions to fetch the object version that may be
 | 
					
						
							|  |  |  | // overwritten or deleted depending on bucket versioning status.
 | 
					
						
							|  |  |  | func (os *objSweeper) GetOpts() ObjectOptions { | 
					
						
							|  |  |  | 	opts := ObjectOptions{ | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | 		VersionID:        os.VersionID, | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 		Versioned:        os.Versioned, | 
					
						
							|  |  |  | 		VersionSuspended: os.Suspended, | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | 	if os.Suspended && os.VersionID == "" { | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 		opts.VersionID = nullVersionID | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return opts | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetTransitionState sets ILM transition related information from given info.
 | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | func (os *objSweeper) SetTransitionState(info TransitionedObject) { | 
					
						
							|  |  |  | 	os.TransitionTier = info.Tier | 
					
						
							|  |  |  | 	os.TransitionStatus = info.Status | 
					
						
							|  |  |  | 	os.RemoteObject = info.Name | 
					
						
							|  |  |  | 	os.TransitionVersionID = info.VersionID | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // shouldRemoveRemoteObject determines if a transitioned object should be
 | 
					
						
							|  |  |  | // removed from remote tier. If remote object is to be deleted, returns the
 | 
					
						
							|  |  |  | // corresponding tier deletion journal entry and true. Otherwise returns empty
 | 
					
						
							|  |  |  | // jentry value and false.
 | 
					
						
							|  |  |  | func (os *objSweeper) shouldRemoveRemoteObject() (jentry, bool) { | 
					
						
							|  |  |  | 	if os.TransitionStatus != lifecycle.TransitionComplete { | 
					
						
							|  |  |  | 		return jentry{}, false | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 1. If bucket versioning is disabled, remove the remote object.
 | 
					
						
							|  |  |  | 	// 2. If bucket versioning is suspended and
 | 
					
						
							|  |  |  | 	//    a. version id is specified, remove its remote object.
 | 
					
						
							|  |  |  | 	//    b. version id is not specified, remove null version's remote object if it exists.
 | 
					
						
							|  |  |  | 	// 3. If bucket versioning is enabled and
 | 
					
						
							|  |  |  | 	//    a. version id is specified, remove its remote object.
 | 
					
						
							|  |  |  | 	//    b. version id is not specified, nothing to be done (a delete marker is added).
 | 
					
						
							|  |  |  | 	delTier := false | 
					
						
							|  |  |  | 	switch { | 
					
						
							|  |  |  | 	case !os.Versioned, os.Suspended: // 1, 2.a, 2.b
 | 
					
						
							|  |  |  | 		delTier = true | 
					
						
							| 
									
										
										
										
											2021-08-17 22:50:00 +08:00
										 |  |  | 	case os.Versioned && os.VersionID != "": // 3.a
 | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 		delTier = true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if delTier { | 
					
						
							| 
									
										
										
										
											2021-06-04 05:26:51 +08:00
										 |  |  | 		return jentry{ | 
					
						
							|  |  |  | 			ObjName:   os.RemoteObject, | 
					
						
							|  |  |  | 			VersionID: os.TransitionVersionID, | 
					
						
							|  |  |  | 			TierName:  os.TransitionTier, | 
					
						
							|  |  |  | 		}, true | 
					
						
							| 
									
										
										
										
											2021-04-20 01:30:42 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return jentry{}, false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Sweep removes the transitioned object if it's no longer referred to.
 | 
					
						
							|  |  |  | func (os *objSweeper) Sweep() error { | 
					
						
							|  |  |  | 	if je, ok := os.shouldRemoveRemoteObject(); ok { | 
					
						
							|  |  |  | 		return globalTierJournal.AddEntry(je) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } |