github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/mirror/utils_test.go (about)

     1  // Package mirror provides local mirroring and replica management
     2  /*
     3   * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved.
     4   */
     5  package mirror_test
     6  
     7  import (
     8  	"os"
     9  	"time"
    10  
    11  	"github.com/NVIDIA/aistore/api/apc"
    12  	"github.com/NVIDIA/aistore/cmn"
    13  	"github.com/NVIDIA/aistore/cmn/cos"
    14  	"github.com/NVIDIA/aistore/core"
    15  	"github.com/NVIDIA/aistore/core/meta"
    16  	"github.com/NVIDIA/aistore/core/mock"
    17  	"github.com/NVIDIA/aistore/fs"
    18  	"github.com/NVIDIA/aistore/tools/readers"
    19  	. "github.com/onsi/ginkgo/v2"
    20  	. "github.com/onsi/gomega"
    21  )
    22  
    23  var _ = Describe("Mirror", func() {
    24  	const (
    25  		testDir = "/tmp/mirror-test_q/"
    26  
    27  		testBucketName = "TEST_LOCAL_MIRROR_BUCKET"
    28  		mpath          = testDir + "mirrortest_mpath/111"
    29  		mpath2         = testDir + "mirrortest_mpath/222"
    30  
    31  		testObjectName = "mirrortestobj.ext"
    32  		testObjectSize = 1234
    33  	)
    34  
    35  	_ = cos.CreateDir(mpath)
    36  	_ = cos.CreateDir(mpath2)
    37  
    38  	config := cmn.GCO.BeginUpdate()
    39  	config.TestFSP.Count = 1
    40  	cmn.GCO.CommitUpdate(config)
    41  
    42  	fs.TestNew(nil)
    43  	_, _ = fs.Add(mpath, "daeID")
    44  	_, _ = fs.Add(mpath2, "daeID")
    45  	fs.CSM.Reg(fs.ObjectType, &fs.ObjectContentResolver{}, true)
    46  	fs.CSM.Reg(fs.WorkfileType, &fs.WorkfileContentResolver{}, true)
    47  
    48  	var (
    49  		props = &cmn.Bprops{
    50  			Cksum:  cmn.CksumConf{Type: cos.ChecksumXXHash},
    51  			LRU:    cmn.LRUConf{Enabled: true},
    52  			Mirror: cmn.MirrorConf{Enabled: true, Copies: 2},
    53  			BID:    1,
    54  		}
    55  		bck             = meta.Bck{Name: testBucketName, Provider: apc.AIS, Ns: cmn.NsGlobal, Props: props}
    56  		bmdMock         = mock.NewBaseBownerMock(&bck)
    57  		mi              = fs.Mountpath{Path: mpath}
    58  		mi2             = fs.Mountpath{Path: mpath2}
    59  		bucketPath      = mi.MakePathCT(bck.Bucket(), fs.ObjectType)
    60  		defaultObjFQN   = mi.MakePathFQN(bck.Bucket(), fs.ObjectType, testObjectName)
    61  		expectedCopyFQN = mi2.MakePathFQN(bck.Bucket(), fs.ObjectType, testObjectName)
    62  	)
    63  
    64  	BeforeEach(func() {
    65  		_ = cos.CreateDir(mpath)
    66  		_ = cos.CreateDir(mpath2)
    67  		_ = mock.NewTarget(bmdMock)
    68  	})
    69  
    70  	AfterEach(func() {
    71  		_ = os.RemoveAll(testDir)
    72  	})
    73  
    74  	// NOTE:
    75  	// the test creates copies; there's a built-in assumption that `mi` will be
    76  	// the HRW mountpath,
    77  	// while `mi2` will not (and, therefore, can be used to place the copy).
    78  	// Ultimately, this depends on the specific HRW hash; adding
    79  	// Expect(lom.IsHRW()).To(BeTrue()) to catch that sooner.
    80  
    81  	Describe("copyTo", func() {
    82  		It("should copy correctly object and set xattrs", func() {
    83  			createTestFile(bucketPath, testObjectName, testObjectSize)
    84  			lom := newBasicLom(defaultObjFQN)
    85  			Expect(lom.IsHRW()).To(BeTrue())
    86  			lom.SetSize(testObjectSize)
    87  			lom.SetAtimeUnix(time.Now().UnixNano())
    88  			Expect(lom.Persist()).NotTo(HaveOccurred())
    89  			Expect(lom.ValidateContentChecksum()).NotTo(HaveOccurred())
    90  
    91  			// Make copy
    92  			lom.Lock(true)
    93  			defer lom.Unlock(true)
    94  			copyFQN := mi2.MakePathFQN(lom.Bucket(), fs.ObjectType, lom.ObjName)
    95  			clone, err := lom.Copy2FQN(copyFQN, nil)
    96  			Expect(err).ShouldNot(HaveOccurred())
    97  			Expect(expectedCopyFQN).To(BeARegularFile())
    98  			Expect(clone.SizeBytes(true)).To(BeEquivalentTo(testObjectSize))
    99  
   100  			// Check copy set
   101  			Expect(clone.IsCopy()).To(BeTrue())
   102  			Expect(clone.NumCopies()).To(Equal(2))
   103  			Expect(clone.GetCopies()).To(And(HaveKey(defaultObjFQN), HaveKey(expectedCopyFQN)))
   104  
   105  			/*
   106  			 * Reload default LOM and copyLOM
   107  			 */
   108  
   109  			// Check reloaded default LOM
   110  			newLOM := newBasicLom(defaultObjFQN)
   111  			Expect(newLOM.IsHRW()).To(BeTrue())
   112  			Expect(newLOM.Load(false, true)).ShouldNot(HaveOccurred())
   113  			Expect(newLOM.IsCopy()).To(BeFalse())
   114  			Expect(newLOM.HasCopies()).To(BeTrue())
   115  			Expect(newLOM.NumCopies()).To(Equal(2))
   116  			Expect(newLOM.GetCopies()).To(And(HaveKey(defaultObjFQN), HaveKey(expectedCopyFQN)))
   117  
   118  			// Check reloaded copyLOM
   119  			copyLOM := newBasicLom(expectedCopyFQN)
   120  			Expect(copyLOM.Load(false, false)).ShouldNot(HaveOccurred())
   121  			copyCksum, err := copyLOM.ComputeSetCksum()
   122  			Expect(err).ShouldNot(HaveOccurred())
   123  			Expect(copyCksum.Value()).To(Equal(newLOM.Checksum().Value()))
   124  			Expect(copyLOM.HrwFQN).To(BeEquivalentTo(lom.HrwFQN))
   125  			Expect(copyLOM.IsCopy()).To(BeTrue())
   126  			Expect(copyLOM.HasCopies()).To(BeTrue())
   127  		})
   128  	})
   129  })
   130  
   131  func createTestFile(filePath, objName string, size int64) {
   132  	err := cos.CreateDir(filePath)
   133  	Expect(err).ShouldNot(HaveOccurred())
   134  
   135  	r, err := readers.NewRandFile(filePath, objName, size, cos.ChecksumNone)
   136  	Expect(err).ShouldNot(HaveOccurred())
   137  	Expect(r.Close()).ShouldNot(HaveOccurred())
   138  }
   139  
   140  func newBasicLom(fqn string) *core.LOM {
   141  	lom := &core.LOM{}
   142  	err := lom.InitFQN(fqn, nil)
   143  	Expect(err).NotTo(HaveOccurred())
   144  	lom.UncacheUnless()
   145  	return lom
   146  }