github.com/swiftstack/ProxyFS@v0.0.0-20210203235616-4017c267d62f/inode/gc_test.go (about)

     1  // Copyright (c) 2015-2021, NVIDIA CORPORATION.
     2  // SPDX-License-Identifier: Apache-2.0
     3  
     4  package inode
     5  
     6  import (
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/swiftstack/ProxyFS/swiftclient"
    11  )
    12  
    13  type testObjectLocationStruct struct {
    14  	accountName   string
    15  	containerName string
    16  	objectName    string
    17  }
    18  
    19  func TestEmptySegmentDeletion(t *testing.T) {
    20  	testSetup(t, false)
    21  
    22  	testVolumeHandle, err := FetchVolumeHandle("TestVolume")
    23  	if nil != err {
    24  		t.Fatalf("FetchVolumeHandle(\"TestVolume\") failed: %v", err)
    25  	}
    26  
    27  	volume := testVolumeHandle.(*volumeStruct)
    28  
    29  	ino, err := testVolumeHandle.CreateFile(PosixModePerm, 0, 0)
    30  	if nil != err {
    31  		t.Fatalf("CreateFile() failed: %v", err)
    32  	}
    33  
    34  	// '$$$$$$$$$$$$$$$$'
    35  	ourBytes := []byte{0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24}
    36  
    37  	// repeatedly write and flush to create some log segments
    38  	for i := 0; i < 5; i++ {
    39  		err := testVolumeHandle.Write(ino, uint64(i*16), ourBytes, nil)
    40  		if err != nil {
    41  			t.Fatalf("failed to write: %v", err)
    42  		}
    43  
    44  		err = testVolumeHandle.Flush(ino, false)
    45  		if err != nil {
    46  			t.Fatalf("failed to flush: %v", err)
    47  		}
    48  	}
    49  
    50  	// inspect log segment map
    51  	ourInode, ok, err := volume.fetchInode(ino)
    52  	if nil != err {
    53  		t.Fatalf("fetchInode(ino==0x%016X) failed: %v", ino, err)
    54  	}
    55  	if !ok {
    56  		t.Fatalf("fetchInode(ino==0x%016X) returned !ok", ino)
    57  	}
    58  	segmentNumbers := make([]uint64, 0, 5)
    59  	segmentObjectLocations := make([]testObjectLocationStruct, 0, 5)
    60  	for segmentNumber := range ourInode.LogSegmentMap {
    61  		segmentNumbers = append(segmentNumbers, segmentNumber)
    62  		containerName, objectName, _, getObjectLocationErr := volume.getObjectLocationFromLogSegmentNumber(segmentNumber)
    63  		if nil != getObjectLocationErr {
    64  			t.Fatalf("expected to be able to get log segment 0x%016X", segmentNumber)
    65  		}
    66  		segmentObjectLocations = append(segmentObjectLocations, testObjectLocationStruct{volume.accountName, containerName, objectName})
    67  	}
    68  
    69  	// overwrite it
    70  	err = testVolumeHandle.Write(ino, 0, make([]byte, 16*5), nil)
    71  	if err != nil {
    72  		t.Fatalf("expected to be able to write to inode #%v", ino)
    73  	}
    74  	err = testVolumeHandle.Flush(ino, false)
    75  	if err != nil {
    76  		t.Fatalf("expected to be able to flush inode #%v", ino)
    77  	}
    78  
    79  	// wait for headhunter checkpoint which blocks deletes
    80  	err = volume.headhunterVolumeHandle.DoCheckpoint()
    81  	if nil != err {
    82  		t.Errorf("expected volume.headhunterVolumeHandle.DoCheckpoint() to succeed: got %v", err)
    83  	}
    84  
    85  	// the deletions are async; give them a (literal) second
    86  	time.Sleep(1 * time.Second)
    87  
    88  	for _, deletedSegmentNumber := range segmentNumbers {
    89  		_, getLogSegmentContainerErr := volume.getLogSegmentContainer(deletedSegmentNumber)
    90  		if getLogSegmentContainerErr == nil {
    91  			t.Errorf("expected volume.getLogSegmentContainer() to fail for allegedly-deleted log segment 0x%016X", deletedSegmentNumber)
    92  		}
    93  	}
    94  
    95  	// the headhunter records got deleted, and ...
    96  	for _, segmentObjectLocation := range segmentObjectLocations {
    97  		var objectContentLengthErr error
    98  
    99  		// wait for up to 20 sec for the object to be (async) deleted
   100  		for try := 0; try < 20; try++ {
   101  			_, objectContentLengthErr = swiftclient.ObjectContentLength(segmentObjectLocation.accountName, segmentObjectLocation.containerName, segmentObjectLocation.objectName)
   102  			//t.Logf("verifying object delete for %v/%v try %d err '%v'\n", segmentObjectLocation.containerName, segmentObjectLocation.objectName, try, objectContentLengthErr)
   103  			if objectContentLengthErr != nil {
   104  				break
   105  			}
   106  			time.Sleep(time.Second)
   107  		}
   108  		if objectContentLengthErr == nil {
   109  			t.Errorf("expected ObjectContentLength() to fail for allegedly-deleted log segment object at %s/%s/%s", segmentObjectLocation.accountName, segmentObjectLocation.containerName, segmentObjectLocation.objectName)
   110  		}
   111  	}
   112  	// the underlying log segment objects got deleted!! Yaaay~! ☆✦❤
   113  
   114  	testTeardown(t)
   115  }